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.
6 #include "base/files/file_path.h"
7 #include "base/synchronization/waitable_event.h"
8 #include "chrome/browser/profiles/profile.h"
9 #include "chrome/browser/ssl/ssl_client_auth_requestor_mock.h"
10 #include "chrome/browser/ui/browser.h"
11 #include "chrome/browser/ui/tabs/tab_strip_model.h"
12 #include "chrome/browser/ui/views/ssl_client_certificate_selector.h"
13 #include "chrome/test/base/in_process_browser_test.h"
14 #include "chrome/test/base/interactive_test_utils.h"
15 #include "chrome/test/base/ui_test_utils.h"
16 #include "content/public/browser/web_contents.h"
17 #include "content/public/test/browser_test_utils.h"
18 #include "net/base/request_priority.h"
19 #include "net/base/test_data_directory.h"
20 #include "net/cert/x509_certificate.h"
21 #include "net/http/http_transaction_factory.h"
22 #include "net/ssl/ssl_cert_request_info.h"
23 #include "net/test/cert_test_util.h"
24 #include "net/url_request/url_request.h"
25 #include "net/url_request/url_request_context.h"
26 #include "net/url_request/url_request_context_getter.h"
27 #include "testing/gtest/include/gtest/gtest.h"
29 using ::testing::Mock;
30 using ::testing::StrictMock;
31 using content::BrowserThread;
33 // We don't have a way to do end-to-end SSL client auth testing, so this test
34 // creates a certificate selector_ manually with a mocked
35 // SSLClientAuthHandler.
37 class SSLClientCertificateSelectorTest : public InProcessBrowserTest {
39 SSLClientCertificateSelectorTest()
40 : io_loop_finished_event_(false, false),
45 virtual void SetUpInProcessBrowserTestFixture() OVERRIDE {
46 base::FilePath certs_dir = net::GetTestCertsDirectory();
48 mit_davidben_cert_ = net::ImportCertFromFile(certs_dir, "mit.davidben.der");
49 ASSERT_NE(static_cast<net::X509Certificate*>(NULL), mit_davidben_cert_);
51 foaf_me_chromium_test_cert_ = net::ImportCertFromFile(
52 certs_dir, "foaf.me.chromium-test-cert.der");
53 ASSERT_NE(static_cast<net::X509Certificate*>(NULL),
54 foaf_me_chromium_test_cert_);
56 cert_request_info_ = new net::SSLCertRequestInfo;
57 cert_request_info_->host_and_port = "foo:123";
58 cert_request_info_->client_certs.push_back(mit_davidben_cert_);
59 cert_request_info_->client_certs.push_back(foaf_me_chromium_test_cert_);
62 virtual void SetUpOnMainThread() OVERRIDE {
63 url_request_context_getter_ = browser()->profile()->GetRequestContext();
65 BrowserThread::PostTask(
66 BrowserThread::IO, FROM_HERE,
67 base::Bind(&SSLClientCertificateSelectorTest::SetUpOnIOThread, this));
69 io_loop_finished_event_.Wait();
71 content::WaitForLoadStop(
72 browser()->tab_strip_model()->GetActiveWebContents());
73 selector_ = new SSLClientCertificateSelector(
74 browser()->tab_strip_model()->GetActiveWebContents(),
75 auth_requestor_->http_network_session_,
76 auth_requestor_->cert_request_info_,
77 base::Bind(&SSLClientAuthRequestorMock::CertificateSelected,
81 EXPECT_EQ(mit_davidben_cert_.get(), selector_->GetSelectedCert());
84 virtual void SetUpOnIOThread() {
85 url_request_ = MakeURLRequest(url_request_context_getter_).release();
87 auth_requestor_ = new StrictMock<SSLClientAuthRequestorMock>(
91 io_loop_finished_event_.Signal();
94 // Have to release our reference to the auth handler during the test to allow
95 // it to be destroyed while the Browser and its IO thread still exist.
96 virtual void CleanUpOnMainThread() OVERRIDE {
97 BrowserThread::PostTask(
98 BrowserThread::IO, FROM_HERE,
99 base::Bind(&SSLClientCertificateSelectorTest::CleanUpOnIOThread, this));
101 io_loop_finished_event_.Wait();
103 auth_requestor_ = NULL;
106 virtual void CleanUpOnIOThread() {
109 io_loop_finished_event_.Signal();
113 scoped_ptr<net::URLRequest> MakeURLRequest(
114 net::URLRequestContextGetter* context_getter) {
115 return context_getter->GetURLRequestContext()->CreateRequest(
116 GURL("https://example"), net::DEFAULT_PRIORITY, NULL);
119 base::WaitableEvent io_loop_finished_event_;
121 scoped_refptr<net::URLRequestContextGetter> url_request_context_getter_;
122 net::URLRequest* url_request_;
124 scoped_refptr<net::X509Certificate> mit_davidben_cert_;
125 scoped_refptr<net::X509Certificate> foaf_me_chromium_test_cert_;
126 scoped_refptr<net::SSLCertRequestInfo> cert_request_info_;
127 scoped_refptr<StrictMock<SSLClientAuthRequestorMock> > auth_requestor_;
128 // The selector will be deleted when a cert is selected or the tab is closed.
129 SSLClientCertificateSelector* selector_;
132 class SSLClientCertificateSelectorMultiTabTest
133 : public SSLClientCertificateSelectorTest {
135 virtual void SetUpInProcessBrowserTestFixture() OVERRIDE {
136 SSLClientCertificateSelectorTest::SetUpInProcessBrowserTestFixture();
138 cert_request_info_1_ = new net::SSLCertRequestInfo;
139 cert_request_info_1_->host_and_port = "bar:123";
140 cert_request_info_1_->client_certs.push_back(mit_davidben_cert_);
141 cert_request_info_1_->client_certs.push_back(foaf_me_chromium_test_cert_);
143 cert_request_info_2_ = new net::SSLCertRequestInfo;
144 cert_request_info_2_->host_and_port = "bar:123";
145 cert_request_info_2_->client_certs.push_back(mit_davidben_cert_);
146 cert_request_info_2_->client_certs.push_back(foaf_me_chromium_test_cert_);
149 virtual void SetUpOnMainThread() OVERRIDE {
150 // Also calls SetUpOnIOThread.
151 SSLClientCertificateSelectorTest::SetUpOnMainThread();
153 AddTabAtIndex(1, GURL("about:blank"), content::PAGE_TRANSITION_LINK);
154 AddTabAtIndex(2, GURL("about:blank"), content::PAGE_TRANSITION_LINK);
155 ASSERT_TRUE(NULL != browser()->tab_strip_model()->GetWebContentsAt(0));
156 ASSERT_TRUE(NULL != browser()->tab_strip_model()->GetWebContentsAt(1));
157 ASSERT_TRUE(NULL != browser()->tab_strip_model()->GetWebContentsAt(2));
158 content::WaitForLoadStop(browser()->tab_strip_model()->GetWebContentsAt(1));
159 content::WaitForLoadStop(browser()->tab_strip_model()->GetWebContentsAt(2));
161 selector_1_ = new SSLClientCertificateSelector(
162 browser()->tab_strip_model()->GetWebContentsAt(1),
163 auth_requestor_1_->http_network_session_,
164 auth_requestor_1_->cert_request_info_,
165 base::Bind(&SSLClientAuthRequestorMock::CertificateSelected,
168 selector_2_ = new SSLClientCertificateSelector(
169 browser()->tab_strip_model()->GetWebContentsAt(2),
170 auth_requestor_2_->http_network_session_,
171 auth_requestor_2_->cert_request_info_,
172 base::Bind(&SSLClientAuthRequestorMock::CertificateSelected,
176 EXPECT_EQ(2, browser()->tab_strip_model()->active_index());
177 EXPECT_EQ(mit_davidben_cert_.get(), selector_1_->GetSelectedCert());
178 EXPECT_EQ(mit_davidben_cert_.get(), selector_2_->GetSelectedCert());
181 virtual void SetUpOnIOThread() OVERRIDE {
182 url_request_1_ = MakeURLRequest(url_request_context_getter_).release();
183 url_request_2_ = MakeURLRequest(url_request_context_getter_).release();
185 auth_requestor_1_ = new StrictMock<SSLClientAuthRequestorMock>(
187 cert_request_info_1_);
188 auth_requestor_2_ = new StrictMock<SSLClientAuthRequestorMock>(
190 cert_request_info_2_);
192 SSLClientCertificateSelectorTest::SetUpOnIOThread();
195 virtual void CleanUpOnMainThread() OVERRIDE {
196 auth_requestor_2_ = NULL;
197 auth_requestor_1_ = NULL;
198 SSLClientCertificateSelectorTest::CleanUpOnMainThread();
201 virtual void CleanUpOnIOThread() OVERRIDE {
202 delete url_request_1_;
203 delete url_request_2_;
204 SSLClientCertificateSelectorTest::CleanUpOnIOThread();
208 net::URLRequest* url_request_1_;
209 net::URLRequest* url_request_2_;
210 scoped_refptr<net::SSLCertRequestInfo> cert_request_info_1_;
211 scoped_refptr<net::SSLCertRequestInfo> cert_request_info_2_;
212 scoped_refptr<StrictMock<SSLClientAuthRequestorMock> > auth_requestor_1_;
213 scoped_refptr<StrictMock<SSLClientAuthRequestorMock> > auth_requestor_2_;
214 SSLClientCertificateSelector* selector_1_;
215 SSLClientCertificateSelector* selector_2_;
218 class SSLClientCertificateSelectorMultiProfileTest
219 : public SSLClientCertificateSelectorTest {
221 virtual void SetUpInProcessBrowserTestFixture() OVERRIDE {
222 SSLClientCertificateSelectorTest::SetUpInProcessBrowserTestFixture();
224 cert_request_info_1_ = new net::SSLCertRequestInfo;
225 cert_request_info_1_->host_and_port = "foo:123";
226 cert_request_info_1_->client_certs.push_back(mit_davidben_cert_);
227 cert_request_info_1_->client_certs.push_back(foaf_me_chromium_test_cert_);
230 virtual void SetUpOnMainThread() OVERRIDE {
231 browser_1_ = CreateIncognitoBrowser();
232 url_request_context_getter_1_ = browser_1_->profile()->GetRequestContext();
234 // Also calls SetUpOnIOThread.
235 SSLClientCertificateSelectorTest::SetUpOnMainThread();
237 selector_1_ = new SSLClientCertificateSelector(
238 browser_1_->tab_strip_model()->GetActiveWebContents(),
239 auth_requestor_1_->http_network_session_,
240 auth_requestor_1_->cert_request_info_,
241 base::Bind(&SSLClientAuthRequestorMock::CertificateSelected,
245 EXPECT_EQ(mit_davidben_cert_.get(), selector_1_->GetSelectedCert());
248 virtual void SetUpOnIOThread() OVERRIDE {
249 url_request_1_ = MakeURLRequest(url_request_context_getter_1_).release();
251 auth_requestor_1_ = new StrictMock<SSLClientAuthRequestorMock>(
253 cert_request_info_1_);
255 SSLClientCertificateSelectorTest::SetUpOnIOThread();
258 virtual void CleanUpOnMainThread() OVERRIDE {
259 auth_requestor_1_ = NULL;
260 SSLClientCertificateSelectorTest::CleanUpOnMainThread();
263 virtual void CleanUpOnIOThread() OVERRIDE {
264 delete url_request_1_;
265 SSLClientCertificateSelectorTest::CleanUpOnIOThread();
270 scoped_refptr<net::URLRequestContextGetter> url_request_context_getter_1_;
271 net::URLRequest* url_request_1_;
272 scoped_refptr<net::SSLCertRequestInfo> cert_request_info_1_;
273 scoped_refptr<StrictMock<SSLClientAuthRequestorMock> > auth_requestor_1_;
274 SSLClientCertificateSelector* selector_1_;
277 IN_PROC_BROWSER_TEST_F(SSLClientCertificateSelectorTest, SelectNone) {
278 EXPECT_CALL(*auth_requestor_, CertificateSelected(NULL));
280 // Let the mock get checked on destruction.
283 // http://crbug.com/121007
284 IN_PROC_BROWSER_TEST_F(SSLClientCertificateSelectorTest, DISABLED_Escape) {
285 EXPECT_CALL(*auth_requestor_, CertificateSelected(NULL));
287 EXPECT_TRUE(ui_test_utils::SendKeyPressSync(
288 browser(), ui::VKEY_ESCAPE, false, false, false, false));
290 Mock::VerifyAndClear(auth_requestor_.get());
293 // Flaky, http://crbug.com/103534 .
294 IN_PROC_BROWSER_TEST_F(SSLClientCertificateSelectorTest,
295 DISABLED_SelectDefault) {
296 EXPECT_CALL(*auth_requestor_, CertificateSelected(mit_davidben_cert_.get()));
298 EXPECT_TRUE(ui_test_utils::SendKeyPressSync(
299 browser(), ui::VKEY_RETURN, false, false, false, false));
301 Mock::VerifyAndClear(auth_requestor_.get());
304 // http://crbug.com/121007
305 IN_PROC_BROWSER_TEST_F(SSLClientCertificateSelectorMultiTabTest,
307 // auth_requestor_1_ should get selected automatically by the
308 // SSLClientAuthObserver when selector_2_ is accepted, since both 1 & 2 have
309 // the same host:port.
310 EXPECT_CALL(*auth_requestor_1_, CertificateSelected(NULL));
311 EXPECT_CALL(*auth_requestor_2_, CertificateSelected(NULL));
313 EXPECT_TRUE(ui_test_utils::SendKeyPressSync(
314 browser(), ui::VKEY_ESCAPE, false, false, false, false));
316 Mock::VerifyAndClear(auth_requestor_.get());
317 Mock::VerifyAndClear(auth_requestor_1_.get());
318 Mock::VerifyAndClear(auth_requestor_2_.get());
320 // Now let the default selection for auth_requestor_ mock get checked on
322 EXPECT_CALL(*auth_requestor_, CertificateSelected(NULL));
325 // http://crbug.com/121007
326 IN_PROC_BROWSER_TEST_F(SSLClientCertificateSelectorMultiTabTest,
327 DISABLED_SelectSecond) {
328 // auth_requestor_1_ should get selected automatically by the
329 // SSLClientAuthObserver when selector_2_ is accepted, since both 1 & 2 have
330 // the same host:port.
331 EXPECT_CALL(*auth_requestor_1_,
332 CertificateSelected(foaf_me_chromium_test_cert_.get()));
333 EXPECT_CALL(*auth_requestor_2_,
334 CertificateSelected(foaf_me_chromium_test_cert_.get()));
336 EXPECT_TRUE(ui_test_utils::SendKeyPressSync(
337 browser(), ui::VKEY_DOWN, false, false, false, false));
339 EXPECT_EQ(mit_davidben_cert_.get(), selector_->GetSelectedCert());
340 EXPECT_EQ(mit_davidben_cert_.get(), selector_1_->GetSelectedCert());
341 EXPECT_EQ(foaf_me_chromium_test_cert_.get(), selector_2_->GetSelectedCert());
343 EXPECT_TRUE(ui_test_utils::SendKeyPressSync(
344 browser(), ui::VKEY_RETURN, false, false, false, false));
346 Mock::VerifyAndClear(auth_requestor_.get());
347 Mock::VerifyAndClear(auth_requestor_1_.get());
348 Mock::VerifyAndClear(auth_requestor_2_.get());
350 // Now let the default selection for auth_requestor_ mock get checked on
352 EXPECT_CALL(*auth_requestor_, CertificateSelected(NULL));
355 // http://crbug.com/103529
356 IN_PROC_BROWSER_TEST_F(SSLClientCertificateSelectorMultiProfileTest,
358 EXPECT_CALL(*auth_requestor_1_, CertificateSelected(NULL));
360 EXPECT_TRUE(ui_test_utils::SendKeyPressSync(
361 browser_1_, ui::VKEY_ESCAPE, false, false, false, false));
363 Mock::VerifyAndClear(auth_requestor_.get());
364 Mock::VerifyAndClear(auth_requestor_1_.get());
366 // Now let the default selection for auth_requestor_ mock get checked on
368 EXPECT_CALL(*auth_requestor_, CertificateSelected(NULL));
371 // http://crbug.com/103534
372 IN_PROC_BROWSER_TEST_F(SSLClientCertificateSelectorMultiProfileTest,
373 DISABLED_SelectDefault) {
374 EXPECT_CALL(*auth_requestor_1_,
375 CertificateSelected(mit_davidben_cert_.get()));
377 EXPECT_TRUE(ui_test_utils::SendKeyPressSync(
378 browser_1_, ui::VKEY_RETURN, false, false, false, false));
380 Mock::VerifyAndClear(auth_requestor_.get());
381 Mock::VerifyAndClear(auth_requestor_1_.get());
383 // Now let the default selection for auth_requestor_ mock get checked on
385 EXPECT_CALL(*auth_requestor_, CertificateSelected(NULL));