ssl_client_certificate_selector_browsertest.cc revision 1320f92c476a1ad9d19dba2a48c72b75566198e9
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. 4 5#include "base/bind.h" 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" 28 29using ::testing::Mock; 30using ::testing::StrictMock; 31using content::BrowserThread; 32 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. 36 37class SSLClientCertificateSelectorTest : public InProcessBrowserTest { 38 public: 39 SSLClientCertificateSelectorTest() 40 : io_loop_finished_event_(false, false), 41 url_request_(NULL), 42 selector_(NULL) { 43 } 44 45 virtual void SetUpInProcessBrowserTestFixture() OVERRIDE { 46 base::FilePath certs_dir = net::GetTestCertsDirectory(); 47 48 mit_davidben_cert_ = net::ImportCertFromFile(certs_dir, "mit.davidben.der"); 49 ASSERT_NE(static_cast<net::X509Certificate*>(NULL), 50 mit_davidben_cert_.get()); 51 52 foaf_me_chromium_test_cert_ = net::ImportCertFromFile( 53 certs_dir, "foaf.me.chromium-test-cert.der"); 54 ASSERT_NE(static_cast<net::X509Certificate*>(NULL), 55 foaf_me_chromium_test_cert_.get()); 56 57 cert_request_info_ = new net::SSLCertRequestInfo; 58 cert_request_info_->host_and_port = net::HostPortPair("foo", 123); 59 cert_request_info_->client_certs.push_back(mit_davidben_cert_); 60 cert_request_info_->client_certs.push_back(foaf_me_chromium_test_cert_); 61 } 62 63 virtual void SetUpOnMainThread() OVERRIDE { 64 url_request_context_getter_ = browser()->profile()->GetRequestContext(); 65 66 BrowserThread::PostTask( 67 BrowserThread::IO, FROM_HERE, 68 base::Bind(&SSLClientCertificateSelectorTest::SetUpOnIOThread, this)); 69 70 io_loop_finished_event_.Wait(); 71 72 content::WaitForLoadStop( 73 browser()->tab_strip_model()->GetActiveWebContents()); 74 selector_ = new SSLClientCertificateSelector( 75 browser()->tab_strip_model()->GetActiveWebContents(), 76 auth_requestor_->http_network_session_, 77 auth_requestor_->cert_request_info_, 78 base::Bind(&SSLClientAuthRequestorMock::CertificateSelected, 79 auth_requestor_)); 80 selector_->Init(); 81 82 EXPECT_EQ(mit_davidben_cert_.get(), selector_->GetSelectedCert()); 83 } 84 85 virtual void SetUpOnIOThread() { 86 url_request_ = MakeURLRequest(url_request_context_getter_.get()).release(); 87 88 auth_requestor_ = new StrictMock<SSLClientAuthRequestorMock>( 89 url_request_, 90 cert_request_info_); 91 92 io_loop_finished_event_.Signal(); 93 } 94 95 // Have to release our reference to the auth handler during the test to allow 96 // it to be destroyed while the Browser and its IO thread still exist. 97 virtual void TearDownOnMainThread() OVERRIDE { 98 BrowserThread::PostTask( 99 BrowserThread::IO, FROM_HERE, 100 base::Bind(&SSLClientCertificateSelectorTest::CleanUpOnIOThread, this)); 101 102 io_loop_finished_event_.Wait(); 103 104 auth_requestor_ = NULL; 105 } 106 107 virtual void CleanUpOnIOThread() { 108 delete url_request_; 109 110 io_loop_finished_event_.Signal(); 111 } 112 113 protected: 114 scoped_ptr<net::URLRequest> MakeURLRequest( 115 net::URLRequestContextGetter* context_getter) { 116 return context_getter->GetURLRequestContext()->CreateRequest( 117 GURL("https://example"), net::DEFAULT_PRIORITY, NULL, NULL); 118 } 119 120 base::WaitableEvent io_loop_finished_event_; 121 122 scoped_refptr<net::URLRequestContextGetter> url_request_context_getter_; 123 net::URLRequest* url_request_; 124 125 scoped_refptr<net::X509Certificate> mit_davidben_cert_; 126 scoped_refptr<net::X509Certificate> foaf_me_chromium_test_cert_; 127 scoped_refptr<net::SSLCertRequestInfo> cert_request_info_; 128 scoped_refptr<StrictMock<SSLClientAuthRequestorMock> > auth_requestor_; 129 // The selector will be deleted when a cert is selected or the tab is closed. 130 SSLClientCertificateSelector* selector_; 131}; 132 133class SSLClientCertificateSelectorMultiTabTest 134 : public SSLClientCertificateSelectorTest { 135 public: 136 virtual void SetUpInProcessBrowserTestFixture() OVERRIDE { 137 SSLClientCertificateSelectorTest::SetUpInProcessBrowserTestFixture(); 138 139 cert_request_info_1_ = new net::SSLCertRequestInfo; 140 cert_request_info_1_->host_and_port = net::HostPortPair("bar", 123); 141 cert_request_info_1_->client_certs.push_back(mit_davidben_cert_); 142 cert_request_info_1_->client_certs.push_back(foaf_me_chromium_test_cert_); 143 144 cert_request_info_2_ = new net::SSLCertRequestInfo; 145 cert_request_info_2_->host_and_port = net::HostPortPair("bar", 123); 146 cert_request_info_2_->client_certs.push_back(mit_davidben_cert_); 147 cert_request_info_2_->client_certs.push_back(foaf_me_chromium_test_cert_); 148 } 149 150 virtual void SetUpOnMainThread() OVERRIDE { 151 // Also calls SetUpOnIOThread. 152 SSLClientCertificateSelectorTest::SetUpOnMainThread(); 153 154 AddTabAtIndex(1, GURL("about:blank"), ui::PAGE_TRANSITION_LINK); 155 AddTabAtIndex(2, GURL("about:blank"), ui::PAGE_TRANSITION_LINK); 156 ASSERT_TRUE(NULL != browser()->tab_strip_model()->GetWebContentsAt(0)); 157 ASSERT_TRUE(NULL != browser()->tab_strip_model()->GetWebContentsAt(1)); 158 ASSERT_TRUE(NULL != browser()->tab_strip_model()->GetWebContentsAt(2)); 159 content::WaitForLoadStop(browser()->tab_strip_model()->GetWebContentsAt(1)); 160 content::WaitForLoadStop(browser()->tab_strip_model()->GetWebContentsAt(2)); 161 162 selector_1_ = new SSLClientCertificateSelector( 163 browser()->tab_strip_model()->GetWebContentsAt(1), 164 auth_requestor_1_->http_network_session_, 165 auth_requestor_1_->cert_request_info_, 166 base::Bind(&SSLClientAuthRequestorMock::CertificateSelected, 167 auth_requestor_1_)); 168 selector_1_->Init(); 169 selector_2_ = new SSLClientCertificateSelector( 170 browser()->tab_strip_model()->GetWebContentsAt(2), 171 auth_requestor_2_->http_network_session_, 172 auth_requestor_2_->cert_request_info_, 173 base::Bind(&SSLClientAuthRequestorMock::CertificateSelected, 174 auth_requestor_2_)); 175 selector_2_->Init(); 176 177 EXPECT_EQ(2, browser()->tab_strip_model()->active_index()); 178 EXPECT_EQ(mit_davidben_cert_.get(), selector_1_->GetSelectedCert()); 179 EXPECT_EQ(mit_davidben_cert_.get(), selector_2_->GetSelectedCert()); 180 } 181 182 virtual void SetUpOnIOThread() OVERRIDE { 183 url_request_1_ = 184 MakeURLRequest(url_request_context_getter_.get()).release(); 185 url_request_2_ = 186 MakeURLRequest(url_request_context_getter_.get()).release(); 187 188 auth_requestor_1_ = new StrictMock<SSLClientAuthRequestorMock>( 189 url_request_1_, 190 cert_request_info_1_); 191 auth_requestor_2_ = new StrictMock<SSLClientAuthRequestorMock>( 192 url_request_2_, 193 cert_request_info_2_); 194 195 SSLClientCertificateSelectorTest::SetUpOnIOThread(); 196 } 197 198 virtual void TearDownOnMainThread() OVERRIDE { 199 auth_requestor_2_ = NULL; 200 auth_requestor_1_ = NULL; 201 SSLClientCertificateSelectorTest::TearDownOnMainThread(); 202 } 203 204 virtual void CleanUpOnIOThread() OVERRIDE { 205 delete url_request_1_; 206 delete url_request_2_; 207 SSLClientCertificateSelectorTest::CleanUpOnIOThread(); 208 } 209 210 protected: 211 net::URLRequest* url_request_1_; 212 net::URLRequest* url_request_2_; 213 scoped_refptr<net::SSLCertRequestInfo> cert_request_info_1_; 214 scoped_refptr<net::SSLCertRequestInfo> cert_request_info_2_; 215 scoped_refptr<StrictMock<SSLClientAuthRequestorMock> > auth_requestor_1_; 216 scoped_refptr<StrictMock<SSLClientAuthRequestorMock> > auth_requestor_2_; 217 SSLClientCertificateSelector* selector_1_; 218 SSLClientCertificateSelector* selector_2_; 219}; 220 221class SSLClientCertificateSelectorMultiProfileTest 222 : public SSLClientCertificateSelectorTest { 223 public: 224 virtual void SetUpInProcessBrowserTestFixture() OVERRIDE { 225 SSLClientCertificateSelectorTest::SetUpInProcessBrowserTestFixture(); 226 227 cert_request_info_1_ = new net::SSLCertRequestInfo; 228 cert_request_info_1_->host_and_port = net::HostPortPair("foo", 123); 229 cert_request_info_1_->client_certs.push_back(mit_davidben_cert_); 230 cert_request_info_1_->client_certs.push_back(foaf_me_chromium_test_cert_); 231 } 232 233 virtual void SetUpOnMainThread() OVERRIDE { 234 browser_1_ = CreateIncognitoBrowser(); 235 url_request_context_getter_1_ = browser_1_->profile()->GetRequestContext(); 236 237 // Also calls SetUpOnIOThread. 238 SSLClientCertificateSelectorTest::SetUpOnMainThread(); 239 240 selector_1_ = new SSLClientCertificateSelector( 241 browser_1_->tab_strip_model()->GetActiveWebContents(), 242 auth_requestor_1_->http_network_session_, 243 auth_requestor_1_->cert_request_info_, 244 base::Bind(&SSLClientAuthRequestorMock::CertificateSelected, 245 auth_requestor_1_)); 246 selector_1_->Init(); 247 248 EXPECT_EQ(mit_davidben_cert_.get(), selector_1_->GetSelectedCert()); 249 } 250 251 virtual void SetUpOnIOThread() OVERRIDE { 252 url_request_1_ = 253 MakeURLRequest(url_request_context_getter_1_.get()).release(); 254 255 auth_requestor_1_ = new StrictMock<SSLClientAuthRequestorMock>( 256 url_request_1_, 257 cert_request_info_1_); 258 259 SSLClientCertificateSelectorTest::SetUpOnIOThread(); 260 } 261 262 virtual void TearDownOnMainThread() OVERRIDE { 263 auth_requestor_1_ = NULL; 264 SSLClientCertificateSelectorTest::TearDownOnMainThread(); 265 } 266 267 virtual void CleanUpOnIOThread() OVERRIDE { 268 delete url_request_1_; 269 SSLClientCertificateSelectorTest::CleanUpOnIOThread(); 270 } 271 272 protected: 273 Browser* browser_1_; 274 scoped_refptr<net::URLRequestContextGetter> url_request_context_getter_1_; 275 net::URLRequest* url_request_1_; 276 scoped_refptr<net::SSLCertRequestInfo> cert_request_info_1_; 277 scoped_refptr<StrictMock<SSLClientAuthRequestorMock> > auth_requestor_1_; 278 SSLClientCertificateSelector* selector_1_; 279}; 280 281#if defined(OS_LINUX) && !defined(OS_CHROMEOS) && defined(USE_AURA) 282// TODO(erg): linux_aura bringup: http://crbug.com/163931 283#define MAYBE_SelectNone DISABLED_SelectNone 284#else 285#define MAYBE_SelectNone SelectNone 286#endif 287 288 289IN_PROC_BROWSER_TEST_F(SSLClientCertificateSelectorTest, MAYBE_SelectNone) { 290 EXPECT_CALL(*auth_requestor_.get(), CertificateSelected(NULL)); 291 292 // Let the mock get checked on destruction. 293} 294 295// http://crbug.com/121007 296IN_PROC_BROWSER_TEST_F(SSLClientCertificateSelectorTest, DISABLED_Escape) { 297 EXPECT_CALL(*auth_requestor_.get(), CertificateSelected(NULL)); 298 299 EXPECT_TRUE(ui_test_utils::SendKeyPressSync( 300 browser(), ui::VKEY_ESCAPE, false, false, false, false)); 301 302 Mock::VerifyAndClear(auth_requestor_.get()); 303} 304 305// Flaky, http://crbug.com/103534 . 306IN_PROC_BROWSER_TEST_F(SSLClientCertificateSelectorTest, 307 DISABLED_SelectDefault) { 308 EXPECT_CALL(*auth_requestor_.get(), 309 CertificateSelected(mit_davidben_cert_.get())); 310 311 EXPECT_TRUE(ui_test_utils::SendKeyPressSync( 312 browser(), ui::VKEY_RETURN, false, false, false, false)); 313 314 Mock::VerifyAndClear(auth_requestor_.get()); 315} 316 317// http://crbug.com/121007 318IN_PROC_BROWSER_TEST_F(SSLClientCertificateSelectorMultiTabTest, 319 DISABLED_Escape) { 320 // auth_requestor_1_ should get selected automatically by the 321 // SSLClientAuthObserver when selector_2_ is accepted, since both 1 & 2 have 322 // the same host:port. 323 EXPECT_CALL(*auth_requestor_1_.get(), CertificateSelected(NULL)); 324 EXPECT_CALL(*auth_requestor_2_.get(), CertificateSelected(NULL)); 325 326 EXPECT_TRUE(ui_test_utils::SendKeyPressSync( 327 browser(), ui::VKEY_ESCAPE, false, false, false, false)); 328 329 Mock::VerifyAndClear(auth_requestor_.get()); 330 Mock::VerifyAndClear(auth_requestor_1_.get()); 331 Mock::VerifyAndClear(auth_requestor_2_.get()); 332 333 // Now let the default selection for auth_requestor_ mock get checked on 334 // destruction. 335 EXPECT_CALL(*auth_requestor_.get(), CertificateSelected(NULL)); 336} 337 338// http://crbug.com/121007 339IN_PROC_BROWSER_TEST_F(SSLClientCertificateSelectorMultiTabTest, 340 DISABLED_SelectSecond) { 341 // auth_requestor_1_ should get selected automatically by the 342 // SSLClientAuthObserver when selector_2_ is accepted, since both 1 & 2 have 343 // the same host:port. 344 EXPECT_CALL(*auth_requestor_1_.get(), 345 CertificateSelected(foaf_me_chromium_test_cert_.get())); 346 EXPECT_CALL(*auth_requestor_2_.get(), 347 CertificateSelected(foaf_me_chromium_test_cert_.get())); 348 349 EXPECT_TRUE(ui_test_utils::SendKeyPressSync( 350 browser(), ui::VKEY_DOWN, false, false, false, false)); 351 352 EXPECT_EQ(mit_davidben_cert_.get(), selector_->GetSelectedCert()); 353 EXPECT_EQ(mit_davidben_cert_.get(), selector_1_->GetSelectedCert()); 354 EXPECT_EQ(foaf_me_chromium_test_cert_.get(), selector_2_->GetSelectedCert()); 355 356 EXPECT_TRUE(ui_test_utils::SendKeyPressSync( 357 browser(), ui::VKEY_RETURN, false, false, false, false)); 358 359 Mock::VerifyAndClear(auth_requestor_.get()); 360 Mock::VerifyAndClear(auth_requestor_1_.get()); 361 Mock::VerifyAndClear(auth_requestor_2_.get()); 362 363 // Now let the default selection for auth_requestor_ mock get checked on 364 // destruction. 365 EXPECT_CALL(*auth_requestor_.get(), CertificateSelected(NULL)); 366} 367 368// http://crbug.com/103529 369IN_PROC_BROWSER_TEST_F(SSLClientCertificateSelectorMultiProfileTest, 370 DISABLED_Escape) { 371 EXPECT_CALL(*auth_requestor_1_.get(), CertificateSelected(NULL)); 372 373 EXPECT_TRUE(ui_test_utils::SendKeyPressSync( 374 browser_1_, ui::VKEY_ESCAPE, false, false, false, false)); 375 376 Mock::VerifyAndClear(auth_requestor_.get()); 377 Mock::VerifyAndClear(auth_requestor_1_.get()); 378 379 // Now let the default selection for auth_requestor_ mock get checked on 380 // destruction. 381 EXPECT_CALL(*auth_requestor_.get(), CertificateSelected(NULL)); 382} 383 384// http://crbug.com/103534 385IN_PROC_BROWSER_TEST_F(SSLClientCertificateSelectorMultiProfileTest, 386 DISABLED_SelectDefault) { 387 EXPECT_CALL(*auth_requestor_1_.get(), 388 CertificateSelected(mit_davidben_cert_.get())); 389 390 EXPECT_TRUE(ui_test_utils::SendKeyPressSync( 391 browser_1_, ui::VKEY_RETURN, false, false, false, false)); 392 393 Mock::VerifyAndClear(auth_requestor_.get()); 394 Mock::VerifyAndClear(auth_requestor_1_.get()); 395 396 // Now let the default selection for auth_requestor_ mock get checked on 397 // destruction. 398 EXPECT_CALL(*auth_requestor_.get(), CertificateSelected(NULL)); 399} 400