OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/profiles/profile.h" | 5 #include "chrome/browser/profiles/profile.h" |
6 | 6 |
7 #include "base/command_line.h" | 7 #include "base/command_line.h" |
8 #include "base/files/file_util.h" | 8 #include "base/files/file_util.h" |
9 #include "base/files/scoped_temp_dir.h" | 9 #include "base/files/scoped_temp_dir.h" |
10 #include "base/json/json_reader.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" | |
11 #include "base/prefs/pref_service.h" | 15 #include "base/prefs/pref_service.h" |
12 #include "base/sequenced_task_runner.h" | 16 #include "base/sequenced_task_runner.h" |
13 #include "base/synchronization/waitable_event.h" | 17 #include "base/synchronization/waitable_event.h" |
14 #include "base/values.h" | 18 #include "base/values.h" |
15 #include "base/version.h" | 19 #include "base/version.h" |
16 #include "chrome/browser/browser_process.h" | 20 #include "chrome/browser/browser_process.h" |
17 #include "chrome/browser/chrome_notification_types.h" | 21 #include "chrome/browser/chrome_notification_types.h" |
22 #include "chrome/browser/net/url_request_mock_util.h" | |
18 #include "chrome/browser/profiles/chrome_version_service.h" | 23 #include "chrome/browser/profiles/chrome_version_service.h" |
19 #include "chrome/browser/profiles/profile_impl.h" | 24 #include "chrome/browser/profiles/profile_impl.h" |
20 #include "chrome/browser/profiles/profile_manager.h" | 25 #include "chrome/browser/profiles/profile_manager.h" |
21 #include "chrome/browser/profiles/startup_task_runner_service.h" | 26 #include "chrome/browser/profiles/startup_task_runner_service.h" |
22 #include "chrome/browser/profiles/startup_task_runner_service_factory.h" | 27 #include "chrome/browser/profiles/startup_task_runner_service_factory.h" |
28 #include "chrome/browser/ui/browser.h" | |
29 #include "chrome/browser/ui/tabs/tab_strip_model.h" | |
23 #include "chrome/common/chrome_constants.h" | 30 #include "chrome/common/chrome_constants.h" |
24 #include "chrome/common/chrome_version_info.h" | 31 #include "chrome/common/chrome_version_info.h" |
25 #include "chrome/common/pref_names.h" | 32 #include "chrome/common/pref_names.h" |
26 #include "chrome/test/base/in_process_browser_test.h" | 33 #include "chrome/test/base/in_process_browser_test.h" |
34 #include "chrome/test/base/ui_test_utils.h" | |
35 #include "content/public/browser/browser_thread.h" | |
27 #include "content/public/test/test_utils.h" | 36 #include "content/public/test/test_utils.h" |
37 #include "net/base/net_errors.h" | |
38 #include "net/test/url_request/url_request_failed_job.h" | |
39 #include "net/url_request/url_fetcher.h" | |
40 #include "net/url_request/url_fetcher_delegate.h" | |
41 #include "net/url_request/url_request_context_getter.h" | |
42 #include "net/url_request/url_request_status.h" | |
28 #include "testing/gmock/include/gmock/gmock.h" | 43 #include "testing/gmock/include/gmock/gmock.h" |
29 #include "testing/gtest/include/gtest/gtest.h" | 44 #include "testing/gtest/include/gtest/gtest.h" |
45 #include "url/gurl.h" | |
30 | 46 |
31 #if defined(OS_CHROMEOS) | 47 #if defined(OS_CHROMEOS) |
32 #include "chrome/browser/chromeos/profiles/profile_helper.h" | 48 #include "chrome/browser/chromeos/profiles/profile_helper.h" |
33 #include "chromeos/chromeos_switches.h" | 49 #include "chromeos/chromeos_switches.h" |
34 #endif | 50 #endif |
35 | 51 |
36 namespace { | 52 namespace { |
37 | 53 |
54 // Simple URLFetcherDelegate with an expected final status and the ability to | |
55 // wait until a request completes. It's not considered a failure for the request | |
56 // to never complete. | |
davidben
2015/05/14 17:09:27
This comment is a little confusing since the metho
mmenke
2015/05/14 19:23:52
Done - I think the last sentence is a bit unexpect
| |
57 class TestURLFetcherDelegate : public net::URLFetcherDelegate { | |
58 public: | |
59 // Creating the TestURLFetcherDelegate automatically creates and starts a | |
60 // URLFetcher. | |
61 TestURLFetcherDelegate( | |
62 scoped_refptr<net::URLRequestContextGetter> context_getter, | |
63 const GURL& url, | |
64 net::URLRequestStatus expected_request_status) | |
65 : expected_request_status_(expected_request_status), | |
66 is_complete_(false), | |
67 fetcher_(net::URLFetcher::Create(url, net::URLFetcher::GET, this)) { | |
68 fetcher_->SetRequestContext(context_getter.get()); | |
69 fetcher_->Start(); | |
70 } | |
71 | |
72 ~TestURLFetcherDelegate() override {} | |
73 | |
74 void OnURLFetchComplete(const net::URLFetcher* source) override { | |
75 EXPECT_EQ(expected_request_status_.status(), source->GetStatus().status()); | |
76 EXPECT_EQ(expected_request_status_.error(), source->GetStatus().error()); | |
77 | |
78 run_loop_.Quit(); | |
79 } | |
80 | |
81 void WaitForCompletion() { | |
82 run_loop_.Run(); | |
83 } | |
84 | |
85 bool is_complete() const { return is_complete_; } | |
86 | |
87 private: | |
88 const net::URLRequestStatus expected_request_status_; | |
89 base::RunLoop run_loop_; | |
90 | |
91 bool is_complete_; | |
92 scoped_ptr<net::URLFetcher> fetcher_; | |
93 | |
94 DISALLOW_COPY_AND_ASSIGN(TestURLFetcherDelegate); | |
95 }; | |
96 | |
38 class MockProfileDelegate : public Profile::Delegate { | 97 class MockProfileDelegate : public Profile::Delegate { |
39 public: | 98 public: |
40 MOCK_METHOD1(OnPrefsLoaded, void(Profile*)); | 99 MOCK_METHOD1(OnPrefsLoaded, void(Profile*)); |
41 MOCK_METHOD3(OnProfileCreated, void(Profile*, bool, bool)); | 100 MOCK_METHOD3(OnProfileCreated, void(Profile*, bool, bool)); |
42 }; | 101 }; |
43 | 102 |
44 // Creates a prefs file in the given directory. | 103 // Creates a prefs file in the given directory. |
45 void CreatePrefsFileInDirectory(const base::FilePath& directory_path) { | 104 void CreatePrefsFileInDirectory(const base::FilePath& directory_path) { |
46 base::FilePath pref_path(directory_path.Append(chrome::kPreferencesFilename)); | 105 base::FilePath pref_path(directory_path.Append(chrome::kPreferencesFilename)); |
47 std::string data("{}"); | 106 std::string data("{}"); |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
93 | 152 |
94 class ProfileBrowserTest : public InProcessBrowserTest { | 153 class ProfileBrowserTest : public InProcessBrowserTest { |
95 protected: | 154 protected: |
96 void SetUpCommandLine(base::CommandLine* command_line) override { | 155 void SetUpCommandLine(base::CommandLine* command_line) override { |
97 #if defined(OS_CHROMEOS) | 156 #if defined(OS_CHROMEOS) |
98 command_line->AppendSwitch( | 157 command_line->AppendSwitch( |
99 chromeos::switches::kIgnoreUserProfileMappingForTests); | 158 chromeos::switches::kIgnoreUserProfileMappingForTests); |
100 #endif | 159 #endif |
101 } | 160 } |
102 | 161 |
162 // content::BrowserTestBase implementation: | |
163 | |
164 void SetUpOnMainThread() override { | |
165 content::BrowserThread::PostTask( | |
166 content::BrowserThread::IO, FROM_HERE, | |
167 base::Bind(&chrome_browser_net::SetUrlRequestMocksEnabled, true)); | |
168 } | |
169 | |
170 void TearDownOnMainThread() override { | |
171 content::BrowserThread::PostTask( | |
172 content::BrowserThread::IO, FROM_HERE, | |
173 base::Bind(&chrome_browser_net::SetUrlRequestMocksEnabled, false)); | |
174 } | |
175 | |
103 scoped_ptr<Profile> CreateProfile( | 176 scoped_ptr<Profile> CreateProfile( |
104 const base::FilePath& path, | 177 const base::FilePath& path, |
105 Profile::Delegate* delegate, | 178 Profile::Delegate* delegate, |
106 Profile::CreateMode create_mode) { | 179 Profile::CreateMode create_mode) { |
107 scoped_ptr<Profile> profile(Profile::CreateProfile( | 180 scoped_ptr<Profile> profile(Profile::CreateProfile( |
108 path, delegate, create_mode)); | 181 path, delegate, create_mode)); |
109 EXPECT_TRUE(profile.get()); | 182 EXPECT_TRUE(profile.get()); |
110 | 183 |
111 // Store the Profile's IO task runner so we can wind it down. | 184 // Store the Profile's IO task runner so we can wind it down. |
112 profile_io_task_runner_ = profile->GetIOTaskRunner(); | 185 profile_io_task_runner_ = profile->GetIOTaskRunner(); |
113 | 186 |
114 return profile.Pass(); | 187 return profile.Pass(); |
115 } | 188 } |
116 | 189 |
117 void FlushIoTaskRunnerAndSpinThreads() { | 190 void FlushIoTaskRunnerAndSpinThreads() { |
118 FlushTaskRunner(profile_io_task_runner_.get()); | 191 FlushTaskRunner(profile_io_task_runner_.get()); |
119 SpinThreads(); | 192 SpinThreads(); |
120 } | 193 } |
121 | 194 |
195 // Starts a test where a URLFetcher is active during profile shutdown. The | |
196 // test completes during teardown of the test fixture. The request should be | |
197 // canceled by |context_getter| during profile shutdown, before the | |
198 // URLRequestContext is destroyed. If that doesn't happen, the Context's | |
199 // will still have oustanding requests during its destruction, and will | |
200 // trigger a CHECK failure. | |
201 void StartActiveFetcherDuringProfileShutdownTest( | |
202 scoped_refptr<net::URLRequestContextGetter> context_getter) { | |
203 // This method should only be called once per test. | |
204 DCHECK(!url_fetcher_delegate_); | |
205 | |
206 // Start a hanging request. This request may or may not completed before | |
207 // the end of the request. | |
208 url_fetcher_delegate_.reset(new TestURLFetcherDelegate( | |
209 context_getter.get(), | |
210 net::URLRequestFailedJob::GetMockHttpUrl(net::ERR_IO_PENDING), | |
211 net::URLRequestStatus(net::URLRequestStatus::CANCELED, | |
212 net::ERR_CONTEXT_SHUT_DOWN))); | |
213 | |
214 // Start a second mock request that just fails, and wait for it to complete. | |
215 // This ensures the first request has reached the network stack. | |
216 TestURLFetcherDelegate url_fetcher_delegate2( | |
217 context_getter.get(), | |
218 net::URLRequestFailedJob::GetMockHttpUrl(net::ERR_FAILED), | |
219 net::URLRequestStatus(net::URLRequestStatus::FAILED, | |
220 net::ERR_FAILED)); | |
221 url_fetcher_delegate2.WaitForCompletion(); | |
davidben
2015/05/14 17:09:27
[Just to confirm, without this line, the test stil
mmenke
2015/05/14 19:23:52
Discussed this offline, clarified comment.
| |
222 | |
223 // The first request should still be hung. | |
224 EXPECT_FALSE(url_fetcher_delegate_->is_complete()); | |
225 } | |
226 | |
227 // Runs a test where an incognito profile's URLFetcher is active during | |
228 // teardown of the profile, and makes sure the request fails as expected. | |
229 // Also tries issuing a request after the incognito profile has been | |
230 // destroyed. | |
231 static void RunURLFetcherActiveDuringIncognitoTeardownTest( | |
232 Browser* incognito_browser, | |
233 scoped_refptr<net::URLRequestContextGetter> context_getter) { | |
234 // Start a hanging request. | |
235 TestURLFetcherDelegate url_fetcher_delegate1( | |
236 context_getter.get(), | |
237 net::URLRequestFailedJob::GetMockHttpUrl(net::ERR_IO_PENDING), | |
238 net::URLRequestStatus(net::URLRequestStatus::CANCELED, | |
239 net::ERR_CONTEXT_SHUT_DOWN)); | |
240 | |
241 // Start a second mock request that just fails, and wait for it to complete. | |
242 // This ensures the first request has reached the network stack. | |
243 TestURLFetcherDelegate url_fetcher_delegate2( | |
244 context_getter.get(), | |
245 net::URLRequestFailedJob::GetMockHttpUrl(net::ERR_FAILED), | |
246 net::URLRequestStatus(net::URLRequestStatus::FAILED, | |
247 net::ERR_FAILED)); | |
248 url_fetcher_delegate2.WaitForCompletion(); | |
249 | |
250 // The first request should still be hung. | |
251 EXPECT_FALSE(url_fetcher_delegate1.is_complete()); | |
252 | |
253 // Close all incognito tabs, starting profile shutdown. | |
254 incognito_browser->tab_strip_model()->CloseAllTabs(); | |
255 | |
256 // The request should have been canceled when the Profile shut down. | |
257 url_fetcher_delegate1.WaitForCompletion(); | |
258 | |
259 // Requests issued after Profile shutdown should fail in a similar manner. | |
260 TestURLFetcherDelegate url_fetcher_delegate3( | |
261 context_getter.get(), | |
262 net::URLRequestFailedJob::GetMockHttpUrl(net::ERR_IO_PENDING), | |
263 net::URLRequestStatus(net::URLRequestStatus::CANCELED, | |
264 net::ERR_CONTEXT_SHUT_DOWN)); | |
265 url_fetcher_delegate3.WaitForCompletion(); | |
266 } | |
267 | |
122 scoped_refptr<base::SequencedTaskRunner> profile_io_task_runner_; | 268 scoped_refptr<base::SequencedTaskRunner> profile_io_task_runner_; |
269 | |
270 // URLFetcherDelegate that outlives the Profile, to test shutdown. | |
271 scoped_ptr<TestURLFetcherDelegate> url_fetcher_delegate_; | |
123 }; | 272 }; |
124 | 273 |
125 // Test OnProfileCreate is called with is_new_profile set to true when | 274 // Test OnProfileCreate is called with is_new_profile set to true when |
126 // creating a new profile synchronously. | 275 // creating a new profile synchronously. |
127 IN_PROC_BROWSER_TEST_F(ProfileBrowserTest, CreateNewProfileSynchronous) { | 276 IN_PROC_BROWSER_TEST_F(ProfileBrowserTest, CreateNewProfileSynchronous) { |
128 base::ScopedTempDir temp_dir; | 277 base::ScopedTempDir temp_dir; |
129 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); | 278 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); |
130 | 279 |
131 MockProfileDelegate delegate; | 280 MockProfileDelegate delegate; |
132 EXPECT_CALL(delegate, OnProfileCreated(testing::NotNull(), true, true)); | 281 EXPECT_CALL(delegate, OnProfileCreated(testing::NotNull(), true, true)); |
(...skipping 269 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
402 ASSERT_EQ(GetExitTypePreferenceFromDisk(profile), "SessionEnded"); | 551 ASSERT_EQ(GetExitTypePreferenceFromDisk(profile), "SessionEnded"); |
403 | 552 |
404 // Mark the success. | 553 // Mark the success. |
405 succeeded = true; | 554 succeeded = true; |
406 } | 555 } |
407 | 556 |
408 ASSERT_TRUE(succeeded) << "profile->EndSession() timed out too often."; | 557 ASSERT_TRUE(succeeded) << "profile->EndSession() timed out too often."; |
409 } | 558 } |
410 | 559 |
411 #endif // defined(USE_X11) || defined(OS_WIN) || defined(USE_OZONE) | 560 #endif // defined(USE_X11) || defined(OS_WIN) || defined(USE_OZONE) |
561 | |
562 // The following tests make sure that it's safe to shut down while one of the | |
563 // Profile's URLRequestContextGetters is in use by a URLFetcher. | |
564 | |
565 IN_PROC_BROWSER_TEST_F(ProfileBrowserTest, | |
566 URLFetcherUsingMainContextDuringShutdown) { | |
567 StartActiveFetcherDuringProfileShutdownTest( | |
568 browser()->profile()->GetRequestContext()); | |
569 } | |
570 | |
571 IN_PROC_BROWSER_TEST_F(ProfileBrowserTest, | |
572 URLFetcherUsingMediaContextDuringShutdown) { | |
573 StartActiveFetcherDuringProfileShutdownTest( | |
574 browser()->profile()->GetMediaRequestContext()); | |
575 } | |
576 | |
577 IN_PROC_BROWSER_TEST_F(ProfileBrowserTest, | |
578 URLFetcherUsingExtensionContextDuringShutdown) { | |
579 StartActiveFetcherDuringProfileShutdownTest( | |
580 browser()->profile()->GetRequestContextForExtensions()); | |
581 } | |
582 | |
583 // The following tests make sure that it's safe to destroy an incognito profile | |
584 // while one of the its URLRequestContextGetters is in use by a URLFetcher. | |
585 | |
586 IN_PROC_BROWSER_TEST_F(ProfileBrowserTest, | |
587 URLFetcherUsingMainContextDuringIncognitoTeardown) { | |
588 Browser* incognito_browser = | |
589 ui_test_utils::OpenURLOffTheRecord(browser()->profile(), | |
590 GURL("about:blank")); | |
591 RunURLFetcherActiveDuringIncognitoTeardownTest( | |
592 incognito_browser, incognito_browser->profile()->GetRequestContext()); | |
593 } | |
594 | |
595 IN_PROC_BROWSER_TEST_F(ProfileBrowserTest, | |
596 URLFetcherUsingExtensionContextDuringIncognitoTeardown) { | |
597 Browser* incognito_browser = | |
598 ui_test_utils::OpenURLOffTheRecord(browser()->profile(), | |
599 GURL("about:blank")); | |
600 RunURLFetcherActiveDuringIncognitoTeardownTest( | |
601 incognito_browser, | |
602 incognito_browser->profile()->GetRequestContextForExtensions()); | |
603 } | |
OLD | NEW |