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.h"
23 #include "chrome/browser/bookmarks/bookmark_model_factory.h"
24 #include "chrome/browser/extensions/extension_service.h"
25 #include "chrome/browser/extensions/test_extension_system.h"
26 #include "chrome/browser/history/history_service.h"
27 #include "chrome/browser/history/history_service_factory.h"
28 #include "chrome/browser/prefs/browser_prefs.h"
29 #include "chrome/common/extensions/extension.h"
30 #include "chrome/common/extensions/extension_constants.h"
31 #include "chrome/common/extensions/permissions/permission_set.h"
32 #include "chrome/test/base/testing_pref_service_syncable.h"
33 #include "chrome/test/base/testing_profile.h"
34 #include "chrome/test/base/ui_test_utils.h"
35 #include "components/user_prefs/pref_registry_syncable.h"
36 #include "content/public/test/test_browser_thread_bundle.h"
37 #include "content/public/test/test_utils.h"
38 #include "extensions/common/manifest_constants.h"
39 #include "testing/gmock/include/gmock/gmock.h"
40 #include "testing/gtest/include/gtest/gtest.h"
42 #if defined(OS_CHROMEOS)
43 #include "chrome/browser/chromeos/login/user_manager.h"
44 #include "chrome/browser/chromeos/settings/cros_settings.h"
45 #include "chrome/browser/chromeos/settings/device_settings_service.h"
51 void GetValueAndQuit(T
* result
, const base::Closure
& quit
, T actual
) {
58 const base::Callback
<void(const base::Callback
<void(T
)>&)>& callback
) {
61 callback
.Run(base::Bind(&GetValueAndQuit
<T
>, &result
, loop
.QuitClosure()));
66 // A pref store that can have its read_error property changed for testing.
67 class TestingPrefStoreWithCustomReadError
: public TestingPrefStore
{
69 TestingPrefStoreWithCustomReadError()
70 : read_error_(PersistentPrefStore::PREF_READ_ERROR_NO_FILE
) {
71 // By default the profile is "new" (NO_FILE means that the profile
72 // wasn't found on disk, so it was created).
74 virtual PrefReadError
GetReadError() const OVERRIDE
{
77 virtual bool IsInitializationComplete() const OVERRIDE
{
80 void set_read_error(PrefReadError read_error
) {
81 read_error_
= read_error
;
84 virtual ~TestingPrefStoreWithCustomReadError() {}
85 PrefReadError read_error_
;
89 const base::FilePath::CharType kExtensionFilePath
[] =
90 FILE_PATH_LITERAL("c:\\foo");
91 #elif defined(OS_POSIX)
92 const base::FilePath::CharType kExtensionFilePath
[] =
93 FILE_PATH_LITERAL("/oo");
96 static scoped_refptr
<extensions::Extension
> CreateExtension(
97 const std::string
& name
,
98 const std::string
& id
) {
99 DictionaryValue manifest
;
100 manifest
.SetString(extensions::manifest_keys::kVersion
, "1.0.0.0");
101 manifest
.SetString(extensions::manifest_keys::kName
, name
);
103 scoped_refptr
<extensions::Extension
> extension
=
104 extensions::Extension::Create(
105 base::FilePath(kExtensionFilePath
).AppendASCII(name
),
106 extensions::Manifest::INTERNAL
,
108 extensions::Extension::NO_FLAGS
,
116 class ProfileSigninConfirmationHelperTest
: public testing::Test
{
118 ProfileSigninConfirmationHelperTest()
123 virtual void SetUp() OVERRIDE
{
124 // Create the profile.
125 TestingProfile::Builder builder
;
126 user_prefs_
= new TestingPrefStoreWithCustomReadError
;
127 TestingPrefServiceSyncable
* pref_service
= new TestingPrefServiceSyncable(
128 new TestingPrefStore(),
130 new TestingPrefStore(),
131 new user_prefs::PrefRegistrySyncable(),
132 new PrefNotifierImpl());
133 chrome::RegisterUserProfilePrefs(pref_service
->registry());
134 builder
.SetPrefService(make_scoped_ptr
<PrefServiceSyncable
>(pref_service
));
135 profile_
= builder
.Build();
137 // Initialize the services we check.
138 profile_
->CreateBookmarkModel(true);
139 model_
= BookmarkModelFactory::GetForProfile(profile_
.get());
140 ui_test_utils::WaitForBookmarkModelToLoad(model_
);
141 ASSERT_TRUE(profile_
->CreateHistoryService(true, false));
142 extensions::TestExtensionSystem
* system
=
143 static_cast<extensions::TestExtensionSystem
*>(
144 extensions::ExtensionSystem::Get(profile_
.get()));
145 CommandLine
command_line(CommandLine::NO_PROGRAM
);
146 system
->CreateExtensionService(&command_line
,
147 base::FilePath(kExtensionFilePath
),
151 virtual void TearDown() OVERRIDE
{
152 // TestExtensionSystem uses DeleteSoon, so we need to delete the profile
153 // and then run the message queue to clean up.
155 base::RunLoop().RunUntilIdle();
159 content::TestBrowserThreadBundle thread_bundle_
;
160 scoped_ptr
<TestingProfile
> profile_
;
161 TestingPrefStoreWithCustomReadError
* user_prefs_
;
162 BookmarkModel
* model_
;
164 #if defined OS_CHROMEOS
165 chromeos::ScopedTestDeviceSettingsService test_device_settings_service_
;
166 chromeos::ScopedTestCrosSettings test_cros_settings_
;
167 chromeos::ScopedTestUserManager test_user_manager_
;
171 TEST_F(ProfileSigninConfirmationHelperTest
, DoNotPromptForNewProfile
) {
172 // Profile is new and there's no profile data.
176 &ui::CheckShouldPromptForNewProfile
,
180 TEST_F(ProfileSigninConfirmationHelperTest
, PromptForNewProfile_Bookmarks
) {
183 // Profile is new but has bookmarks.
184 model_
->AddURL(model_
->bookmark_bar_node(), 0, string16(ASCIIToUTF16("foo")),
185 GURL("http://foo.com"));
189 &ui::CheckShouldPromptForNewProfile
,
193 TEST_F(ProfileSigninConfirmationHelperTest
, PromptForNewProfile_Extensions
) {
194 ExtensionService
* extensions
=
195 extensions::ExtensionSystem::Get(profile_
.get())->extension_service();
196 ASSERT_TRUE(extensions
);
198 // Profile is new but has synced extensions.
200 // (The web store doesn't count.)
201 scoped_refptr
<extensions::Extension
> webstore
=
202 CreateExtension("web store", extension_misc::kWebStoreAppId
);
203 extensions
->extension_prefs()->AddGrantedPermissions(
204 webstore
->id(), make_scoped_refptr(new extensions::PermissionSet
).get());
205 extensions
->AddExtension(webstore
.get());
206 EXPECT_FALSE(GetCallbackResult(
207 base::Bind(&ui::CheckShouldPromptForNewProfile
, profile_
.get())));
209 scoped_refptr
<extensions::Extension
> extension
=
210 CreateExtension("foo", std::string());
211 extensions
->extension_prefs()->AddGrantedPermissions(
212 extension
->id(), make_scoped_refptr(new extensions::PermissionSet
).get());
213 extensions
->AddExtension(extension
.get());
214 EXPECT_TRUE(GetCallbackResult(
215 base::Bind(&ui::CheckShouldPromptForNewProfile
, profile_
.get())));
218 TEST_F(ProfileSigninConfirmationHelperTest
, PromptForNewProfile_History
) {
219 HistoryService
* history
= HistoryServiceFactory::GetForProfile(
221 Profile::EXPLICIT_ACCESS
);
222 ASSERT_TRUE(history
);
224 // Profile is new but has more than $(kHistoryEntriesBeforeNewProfilePrompt)
227 for (int i
= 0; i
< 10; i
++) {
228 base::snprintf(buf
, arraysize(buf
), "http://foo.com/%d", i
);
230 GURL(std::string(buf
)), base::Time::Now(), NULL
, 1,
231 GURL(), history::RedirectList(), content::PAGE_TRANSITION_LINK
,
232 history::SOURCE_BROWSED
, false);
237 &ui::CheckShouldPromptForNewProfile
,
241 TEST_F(ProfileSigninConfirmationHelperTest
, PromptForNewProfile_TypedURLs
) {
242 HistoryService
* history
= HistoryServiceFactory::GetForProfile(
244 Profile::EXPLICIT_ACCESS
);
245 ASSERT_TRUE(history
);
247 // Profile is new but has a typed URL.
249 GURL("http://example.com"), base::Time::Now(), NULL
, 1,
250 GURL(), history::RedirectList(), content::PAGE_TRANSITION_TYPED
,
251 history::SOURCE_BROWSED
, false);
255 &ui::CheckShouldPromptForNewProfile
,
259 TEST_F(ProfileSigninConfirmationHelperTest
, PromptForNewProfile_Restarted
) {
260 // Browser has been shut down since profile was created.
261 user_prefs_
->set_read_error(PersistentPrefStore::PREF_READ_ERROR_NONE
);
265 &ui::CheckShouldPromptForNewProfile
,