Popular sites on the NTP: re-download popular suggestions once per Chrome run
[chromium-blink-merge.git] / chrome / browser / profiles / profile_browsertest.cc
blob72b1ee7d4ba07cdf8e52d38af7c3b897f7e7c162
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.
5 #include "chrome/browser/profiles/profile.h"
7 #include "base/command_line.h"
8 #include "base/files/file_util.h"
9 #include "base/files/scoped_temp_dir.h"
10 #include "base/json/json_reader.h"
11 #include "base/logging.h"
12 #include "base/macros.h"
13 #include "base/memory/ref_counted.h"
14 #include "base/memory/scoped_ptr.h"
15 #include "base/prefs/pref_service.h"
16 #include "base/sequenced_task_runner.h"
17 #include "base/synchronization/waitable_event.h"
18 #include "base/values.h"
19 #include "base/version.h"
20 #include "chrome/browser/browser_process.h"
21 #include "chrome/browser/chrome_notification_types.h"
22 #include "chrome/browser/net/url_request_mock_util.h"
23 #include "chrome/browser/profiles/chrome_version_service.h"
24 #include "chrome/browser/profiles/profile_impl.h"
25 #include "chrome/browser/profiles/profile_manager.h"
26 #include "chrome/browser/ui/browser.h"
27 #include "chrome/browser/ui/tabs/tab_strip_model.h"
28 #include "chrome/common/chrome_constants.h"
29 #include "chrome/common/pref_names.h"
30 #include "chrome/test/base/in_process_browser_test.h"
31 #include "chrome/test/base/ui_test_utils.h"
32 #include "components/bookmarks/browser/startup_task_runner_service.h"
33 #include "components/version_info/version_info.h"
34 #include "content/public/browser/browser_thread.h"
35 #include "content/public/test/test_utils.h"
36 #include "net/base/net_errors.h"
37 #include "net/test/url_request/url_request_failed_job.h"
38 #include "net/url_request/url_fetcher.h"
39 #include "net/url_request/url_fetcher_delegate.h"
40 #include "net/url_request/url_request_context_getter.h"
41 #include "net/url_request/url_request_status.h"
42 #include "testing/gmock/include/gmock/gmock.h"
43 #include "testing/gtest/include/gtest/gtest.h"
44 #include "url/gurl.h"
46 #if defined(OS_CHROMEOS)
47 #include "chrome/browser/chromeos/profiles/profile_helper.h"
48 #include "chromeos/chromeos_switches.h"
49 #endif
51 namespace {
53 // Simple URLFetcherDelegate with an expected final status and the ability to
54 // wait until a request completes. It's not considered a failure for the request
55 // to never complete.
56 class TestURLFetcherDelegate : public net::URLFetcherDelegate {
57 public:
58 // Creating the TestURLFetcherDelegate automatically creates and starts a
59 // URLFetcher.
60 TestURLFetcherDelegate(
61 scoped_refptr<net::URLRequestContextGetter> context_getter,
62 const GURL& url,
63 net::URLRequestStatus expected_request_status)
64 : expected_request_status_(expected_request_status),
65 is_complete_(false),
66 fetcher_(net::URLFetcher::Create(url, net::URLFetcher::GET, this)) {
67 fetcher_->SetRequestContext(context_getter.get());
68 fetcher_->Start();
71 ~TestURLFetcherDelegate() override {}
73 void OnURLFetchComplete(const net::URLFetcher* source) override {
74 EXPECT_EQ(expected_request_status_.status(), source->GetStatus().status());
75 EXPECT_EQ(expected_request_status_.error(), source->GetStatus().error());
77 run_loop_.Quit();
80 void WaitForCompletion() {
81 run_loop_.Run();
84 bool is_complete() const { return is_complete_; }
86 private:
87 const net::URLRequestStatus expected_request_status_;
88 base::RunLoop run_loop_;
90 bool is_complete_;
91 scoped_ptr<net::URLFetcher> fetcher_;
93 DISALLOW_COPY_AND_ASSIGN(TestURLFetcherDelegate);
96 class MockProfileDelegate : public Profile::Delegate {
97 public:
98 MOCK_METHOD1(OnPrefsLoaded, void(Profile*));
99 MOCK_METHOD3(OnProfileCreated, void(Profile*, bool, bool));
102 // Creates a prefs file in the given directory.
103 void CreatePrefsFileInDirectory(const base::FilePath& directory_path) {
104 base::FilePath pref_path(directory_path.Append(chrome::kPreferencesFilename));
105 std::string data("{}");
106 ASSERT_TRUE(base::WriteFile(pref_path, data.c_str(), data.size()));
109 void CheckChromeVersion(Profile *profile, bool is_new) {
110 std::string created_by_version;
111 if (is_new) {
112 created_by_version = version_info::GetVersionNumber();
113 } else {
114 created_by_version = "1.0.0.0";
116 std::string pref_version =
117 ChromeVersionService::GetVersion(profile->GetPrefs());
118 // Assert that created_by_version pref gets set to current version.
119 EXPECT_EQ(created_by_version, pref_version);
122 void FlushTaskRunner(base::SequencedTaskRunner* runner) {
123 ASSERT_TRUE(runner);
124 base::WaitableEvent unblock(false, false);
126 runner->PostTask(FROM_HERE,
127 base::Bind(&base::WaitableEvent::Signal, base::Unretained(&unblock)));
129 unblock.Wait();
132 void SpinThreads() {
133 // Give threads a chance to do their stuff before shutting down (i.e.
134 // deleting scoped temp dir etc).
135 // Should not be necessary anymore once Profile deletion is fixed
136 // (see crbug.com/88586).
137 content::RunAllPendingInMessageLoop();
138 content::RunAllPendingInMessageLoop(content::BrowserThread::DB);
139 content::RunAllPendingInMessageLoop(content::BrowserThread::FILE);
142 } // namespace
144 class ProfileBrowserTest : public InProcessBrowserTest {
145 protected:
146 void SetUpCommandLine(base::CommandLine* command_line) override {
147 #if defined(OS_CHROMEOS)
148 command_line->AppendSwitch(
149 chromeos::switches::kIgnoreUserProfileMappingForTests);
150 #endif
153 // content::BrowserTestBase implementation:
155 void SetUpOnMainThread() override {
156 content::BrowserThread::PostTask(
157 content::BrowserThread::IO, FROM_HERE,
158 base::Bind(&chrome_browser_net::SetUrlRequestMocksEnabled, true));
161 void TearDownOnMainThread() override {
162 content::BrowserThread::PostTask(
163 content::BrowserThread::IO, FROM_HERE,
164 base::Bind(&chrome_browser_net::SetUrlRequestMocksEnabled, false));
167 scoped_ptr<Profile> CreateProfile(
168 const base::FilePath& path,
169 Profile::Delegate* delegate,
170 Profile::CreateMode create_mode) {
171 scoped_ptr<Profile> profile(Profile::CreateProfile(
172 path, delegate, create_mode));
173 EXPECT_TRUE(profile.get());
175 // Store the Profile's IO task runner so we can wind it down.
176 profile_io_task_runner_ = profile->GetIOTaskRunner();
178 return profile.Pass();
181 void FlushIoTaskRunnerAndSpinThreads() {
182 FlushTaskRunner(profile_io_task_runner_.get());
183 SpinThreads();
186 // Starts a test where a URLFetcher is active during profile shutdown. The
187 // test completes during teardown of the test fixture. The request should be
188 // canceled by |context_getter| during profile shutdown, before the
189 // URLRequestContext is destroyed. If that doesn't happen, the Context's
190 // will still have oustanding requests during its destruction, and will
191 // trigger a CHECK failure.
192 void StartActiveFetcherDuringProfileShutdownTest(
193 scoped_refptr<net::URLRequestContextGetter> context_getter) {
194 // This method should only be called once per test.
195 DCHECK(!url_fetcher_delegate_);
197 // Start a hanging request. This request may or may not completed before
198 // the end of the request.
199 url_fetcher_delegate_.reset(new TestURLFetcherDelegate(
200 context_getter.get(),
201 net::URLRequestFailedJob::GetMockHttpUrl(net::ERR_IO_PENDING),
202 net::URLRequestStatus(net::URLRequestStatus::CANCELED,
203 net::ERR_CONTEXT_SHUT_DOWN)));
205 // Start a second mock request that just fails, and wait for it to complete.
206 // This ensures the first request has reached the network stack.
207 TestURLFetcherDelegate url_fetcher_delegate2(
208 context_getter.get(),
209 net::URLRequestFailedJob::GetMockHttpUrl(net::ERR_FAILED),
210 net::URLRequestStatus(net::URLRequestStatus::FAILED,
211 net::ERR_FAILED));
212 url_fetcher_delegate2.WaitForCompletion();
214 // The first request should still be hung.
215 EXPECT_FALSE(url_fetcher_delegate_->is_complete());
218 // Runs a test where an incognito profile's URLFetcher is active during
219 // teardown of the profile, and makes sure the request fails as expected.
220 // Also tries issuing a request after the incognito profile has been
221 // destroyed.
222 static void RunURLFetcherActiveDuringIncognitoTeardownTest(
223 Browser* incognito_browser,
224 scoped_refptr<net::URLRequestContextGetter> context_getter) {
225 // Start a hanging request.
226 TestURLFetcherDelegate url_fetcher_delegate1(
227 context_getter.get(),
228 net::URLRequestFailedJob::GetMockHttpUrl(net::ERR_IO_PENDING),
229 net::URLRequestStatus(net::URLRequestStatus::CANCELED,
230 net::ERR_CONTEXT_SHUT_DOWN));
232 // Start a second mock request that just fails, and wait for it to complete.
233 // This ensures the first request has reached the network stack.
234 TestURLFetcherDelegate url_fetcher_delegate2(
235 context_getter.get(),
236 net::URLRequestFailedJob::GetMockHttpUrl(net::ERR_FAILED),
237 net::URLRequestStatus(net::URLRequestStatus::FAILED,
238 net::ERR_FAILED));
239 url_fetcher_delegate2.WaitForCompletion();
241 // The first request should still be hung.
242 EXPECT_FALSE(url_fetcher_delegate1.is_complete());
244 // Close all incognito tabs, starting profile shutdown.
245 incognito_browser->tab_strip_model()->CloseAllTabs();
247 // The request should have been canceled when the Profile shut down.
248 url_fetcher_delegate1.WaitForCompletion();
250 // Requests issued after Profile shutdown should fail in a similar manner.
251 TestURLFetcherDelegate url_fetcher_delegate3(
252 context_getter.get(),
253 net::URLRequestFailedJob::GetMockHttpUrl(net::ERR_IO_PENDING),
254 net::URLRequestStatus(net::URLRequestStatus::CANCELED,
255 net::ERR_CONTEXT_SHUT_DOWN));
256 url_fetcher_delegate3.WaitForCompletion();
259 scoped_refptr<base::SequencedTaskRunner> profile_io_task_runner_;
261 // URLFetcherDelegate that outlives the Profile, to test shutdown.
262 scoped_ptr<TestURLFetcherDelegate> url_fetcher_delegate_;
265 // Test OnProfileCreate is called with is_new_profile set to true when
266 // creating a new profile synchronously.
267 IN_PROC_BROWSER_TEST_F(ProfileBrowserTest, CreateNewProfileSynchronous) {
268 base::ScopedTempDir temp_dir;
269 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
271 MockProfileDelegate delegate;
272 EXPECT_CALL(delegate, OnProfileCreated(testing::NotNull(), true, true));
275 scoped_ptr<Profile> profile(CreateProfile(
276 temp_dir.path(), &delegate, Profile::CREATE_MODE_SYNCHRONOUS));
277 CheckChromeVersion(profile.get(), true);
280 FlushIoTaskRunnerAndSpinThreads();
283 // Test OnProfileCreate is called with is_new_profile set to false when
284 // creating a profile synchronously with an existing prefs file.
285 IN_PROC_BROWSER_TEST_F(ProfileBrowserTest, CreateOldProfileSynchronous) {
286 base::ScopedTempDir temp_dir;
287 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
288 CreatePrefsFileInDirectory(temp_dir.path());
290 MockProfileDelegate delegate;
291 EXPECT_CALL(delegate, OnProfileCreated(testing::NotNull(), true, false));
294 scoped_ptr<Profile> profile(CreateProfile(
295 temp_dir.path(), &delegate, Profile::CREATE_MODE_SYNCHRONOUS));
296 CheckChromeVersion(profile.get(), false);
299 FlushIoTaskRunnerAndSpinThreads();
302 // Flaky: http://crbug.com/393177
303 // Test OnProfileCreate is called with is_new_profile set to true when
304 // creating a new profile asynchronously.
305 IN_PROC_BROWSER_TEST_F(ProfileBrowserTest,
306 DISABLED_CreateNewProfileAsynchronous) {
307 base::ScopedTempDir temp_dir;
308 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
310 MockProfileDelegate delegate;
311 EXPECT_CALL(delegate, OnProfileCreated(testing::NotNull(), true, true));
314 content::WindowedNotificationObserver observer(
315 chrome::NOTIFICATION_PROFILE_CREATED,
316 content::NotificationService::AllSources());
318 scoped_ptr<Profile> profile(CreateProfile(
319 temp_dir.path(), &delegate, Profile::CREATE_MODE_ASYNCHRONOUS));
321 // Wait for the profile to be created.
322 observer.Wait();
323 CheckChromeVersion(profile.get(), true);
326 FlushIoTaskRunnerAndSpinThreads();
330 // Flaky: http://crbug.com/393177
331 // Test OnProfileCreate is called with is_new_profile set to false when
332 // creating a profile asynchronously with an existing prefs file.
333 IN_PROC_BROWSER_TEST_F(ProfileBrowserTest,
334 DISABLED_CreateOldProfileAsynchronous) {
335 base::ScopedTempDir temp_dir;
336 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
337 CreatePrefsFileInDirectory(temp_dir.path());
339 MockProfileDelegate delegate;
340 EXPECT_CALL(delegate, OnProfileCreated(testing::NotNull(), true, false));
343 content::WindowedNotificationObserver observer(
344 chrome::NOTIFICATION_PROFILE_CREATED,
345 content::NotificationService::AllSources());
347 scoped_ptr<Profile> profile(CreateProfile(
348 temp_dir.path(), &delegate, Profile::CREATE_MODE_ASYNCHRONOUS));
350 // Wait for the profile to be created.
351 observer.Wait();
352 CheckChromeVersion(profile.get(), false);
355 FlushIoTaskRunnerAndSpinThreads();
358 // Flaky: http://crbug.com/393177
359 // Test that a README file is created for profiles that didn't have it.
360 IN_PROC_BROWSER_TEST_F(ProfileBrowserTest, DISABLED_ProfileReadmeCreated) {
361 base::ScopedTempDir temp_dir;
362 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
364 MockProfileDelegate delegate;
365 EXPECT_CALL(delegate, OnProfileCreated(testing::NotNull(), true, true));
368 content::WindowedNotificationObserver observer(
369 chrome::NOTIFICATION_PROFILE_CREATED,
370 content::NotificationService::AllSources());
372 scoped_ptr<Profile> profile(CreateProfile(
373 temp_dir.path(), &delegate, Profile::CREATE_MODE_ASYNCHRONOUS));
375 // Wait for the profile to be created.
376 observer.Wait();
378 // Verify that README exists.
379 EXPECT_TRUE(base::PathExists(
380 temp_dir.path().Append(chrome::kReadmeFilename)));
383 FlushIoTaskRunnerAndSpinThreads();
386 // Test that repeated setting of exit type is handled correctly.
387 IN_PROC_BROWSER_TEST_F(ProfileBrowserTest, ExitType) {
388 base::ScopedTempDir temp_dir;
389 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
391 MockProfileDelegate delegate;
392 EXPECT_CALL(delegate, OnProfileCreated(testing::NotNull(), true, true));
394 scoped_ptr<Profile> profile(CreateProfile(
395 temp_dir.path(), &delegate, Profile::CREATE_MODE_SYNCHRONOUS));
397 PrefService* prefs = profile->GetPrefs();
398 // The initial state is crashed; store for later reference.
399 std::string crash_value(prefs->GetString(prefs::kSessionExitType));
401 // The first call to a type other than crashed should change the value.
402 profile->SetExitType(Profile::EXIT_SESSION_ENDED);
403 std::string first_call_value(prefs->GetString(prefs::kSessionExitType));
404 EXPECT_NE(crash_value, first_call_value);
406 // Subsequent calls to a non-crash value should be ignored.
407 profile->SetExitType(Profile::EXIT_NORMAL);
408 std::string second_call_value(prefs->GetString(prefs::kSessionExitType));
409 EXPECT_EQ(first_call_value, second_call_value);
411 // Setting back to a crashed value should work.
412 profile->SetExitType(Profile::EXIT_CRASHED);
413 std::string final_value(prefs->GetString(prefs::kSessionExitType));
414 EXPECT_EQ(crash_value, final_value);
417 FlushIoTaskRunnerAndSpinThreads();
420 // The EndSession IO synchronization is only critical on Windows, but also
421 // happens under the USE_X11 define. See BrowserProcessImpl::EndSession.
422 #if defined(USE_X11) || defined(OS_WIN) || defined(USE_OZONE)
424 namespace {
426 std::string GetExitTypePreferenceFromDisk(Profile* profile) {
427 base::FilePath prefs_path =
428 profile->GetPath().Append(chrome::kPreferencesFilename);
429 std::string prefs;
430 if (!base::ReadFileToString(prefs_path, &prefs))
431 return std::string();
433 scoped_ptr<base::Value> value = base::JSONReader::Read(prefs);
434 if (!value)
435 return std::string();
437 base::DictionaryValue* dict = NULL;
438 if (!value->GetAsDictionary(&dict) || !dict)
439 return std::string();
441 std::string exit_type;
442 if (!dict->GetString("profile.exit_type", &exit_type))
443 return std::string();
445 return exit_type;
448 } // namespace
450 IN_PROC_BROWSER_TEST_F(ProfileBrowserTest,
451 WritesProfilesSynchronouslyOnEndSession) {
452 base::ScopedTempDir temp_dir;
453 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
455 ProfileManager* profile_manager = g_browser_process->profile_manager();
456 ASSERT_TRUE(profile_manager);
457 std::vector<Profile*> loaded_profiles = profile_manager->GetLoadedProfiles();
459 ASSERT_NE(loaded_profiles.size(), 0UL);
460 Profile* profile = loaded_profiles[0];
462 #if defined(OS_CHROMEOS)
463 for (const auto& loaded_profile : loaded_profiles) {
464 if (!chromeos::ProfileHelper::IsSigninProfile(loaded_profile)) {
465 profile = loaded_profile;
466 break;
469 #endif
471 // This retry loop reduces flakiness due to the fact that this ultimately
472 // tests whether or not a code path hits a timed wait.
473 bool succeeded = false;
474 for (size_t retries = 0; !succeeded && retries < 3; ++retries) {
475 // Flush the profile data to disk for all loaded profiles.
476 profile->SetExitType(Profile::EXIT_CRASHED);
477 profile->GetPrefs()->CommitPendingWrite();
478 FlushTaskRunner(profile->GetIOTaskRunner().get());
480 // Make sure that the prefs file was written with the expected key/value.
481 ASSERT_EQ(GetExitTypePreferenceFromDisk(profile), "Crashed");
483 // The blocking wait in EndSession has a timeout.
484 base::Time start = base::Time::Now();
486 // This must not return until the profile data has been written to disk.
487 // If this test flakes, then logoff on Windows has broken again.
488 g_browser_process->EndSession();
490 base::Time end = base::Time::Now();
492 // The EndSession timeout is 10 seconds. If we take more than half that,
493 // go around again, as we may have timed out on the wait.
494 // This helps against flakes, and also ensures that if the IO thread starts
495 // blocking systemically for that length of time (e.g. deadlocking or such),
496 // we'll get a consistent test failure.
497 if (end - start > base::TimeDelta::FromSeconds(5))
498 continue;
500 // Make sure that the prefs file was written with the expected key/value.
501 ASSERT_EQ(GetExitTypePreferenceFromDisk(profile), "SessionEnded");
503 // Mark the success.
504 succeeded = true;
507 ASSERT_TRUE(succeeded) << "profile->EndSession() timed out too often.";
510 #endif // defined(USE_X11) || defined(OS_WIN) || defined(USE_OZONE)
512 // The following tests make sure that it's safe to shut down while one of the
513 // Profile's URLRequestContextGetters is in use by a URLFetcher.
515 IN_PROC_BROWSER_TEST_F(ProfileBrowserTest,
516 URLFetcherUsingMainContextDuringShutdown) {
517 StartActiveFetcherDuringProfileShutdownTest(
518 browser()->profile()->GetRequestContext());
521 IN_PROC_BROWSER_TEST_F(ProfileBrowserTest,
522 URLFetcherUsingMediaContextDuringShutdown) {
523 StartActiveFetcherDuringProfileShutdownTest(
524 browser()->profile()->GetMediaRequestContext());
527 IN_PROC_BROWSER_TEST_F(ProfileBrowserTest,
528 URLFetcherUsingExtensionContextDuringShutdown) {
529 StartActiveFetcherDuringProfileShutdownTest(
530 browser()->profile()->GetRequestContextForExtensions());
533 // The following tests make sure that it's safe to destroy an incognito profile
534 // while one of the its URLRequestContextGetters is in use by a URLFetcher.
536 IN_PROC_BROWSER_TEST_F(ProfileBrowserTest,
537 URLFetcherUsingMainContextDuringIncognitoTeardown) {
538 Browser* incognito_browser =
539 OpenURLOffTheRecord(browser()->profile(), GURL("about:blank"));
540 RunURLFetcherActiveDuringIncognitoTeardownTest(
541 incognito_browser, incognito_browser->profile()->GetRequestContext());
544 IN_PROC_BROWSER_TEST_F(ProfileBrowserTest,
545 URLFetcherUsingExtensionContextDuringIncognitoTeardown) {
546 Browser* incognito_browser =
547 OpenURLOffTheRecord(browser()->profile(), GURL("about:blank"));
549 RunURLFetcherActiveDuringIncognitoTeardownTest(
550 incognito_browser,
551 incognito_browser->profile()->GetRequestContextForExtensions());