ssl_client_certificate_selector_browsertest.cc revision 5f1c94371a64b3196d4be9466099bb892df9b88e
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), mit_davidben_cert_); 50 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_); 55 56 cert_request_info_ = new net::SSLCertRequestInfo; 57 cert_request_info_->host_and_port = net::HostPortPair("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_); 60 } 61 62 virtual void SetUpOnMainThread() OVERRIDE { 63 url_request_context_getter_ = browser()->profile()->GetRequestContext(); 64 65 BrowserThread::PostTask( 66 BrowserThread::IO, FROM_HERE, 67 base::Bind(&SSLClientCertificateSelectorTest::SetUpOnIOThread, this)); 68 69 io_loop_finished_event_.Wait(); 70 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, 78 auth_requestor_)); 79 selector_->Init(); 80 81 EXPECT_EQ(mit_davidben_cert_.get(), selector_->GetSelectedCert()); 82 } 83 84 virtual void SetUpOnIOThread() { 85 url_request_ = MakeURLRequest(url_request_context_getter_).release(); 86 87 auth_requestor_ = new StrictMock<SSLClientAuthRequestorMock>( 88 url_request_, 89 cert_request_info_); 90 91 io_loop_finished_event_.Signal(); 92 } 93 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 TearDownOnMainThread() OVERRIDE { 97 BrowserThread::PostTask( 98 BrowserThread::IO, FROM_HERE, 99 base::Bind(&SSLClientCertificateSelectorTest::CleanUpOnIOThread, this)); 100 101 io_loop_finished_event_.Wait(); 102 103 auth_requestor_ = NULL; 104 } 105 106 virtual void CleanUpOnIOThread() { 107 delete url_request_; 108 109 io_loop_finished_event_.Signal(); 110 } 111 112 protected: 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, NULL); 117 } 118 119 base::WaitableEvent io_loop_finished_event_; 120 121 scoped_refptr<net::URLRequestContextGetter> url_request_context_getter_; 122 net::URLRequest* url_request_; 123 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_; 130}; 131 132class SSLClientCertificateSelectorMultiTabTest 133 : public SSLClientCertificateSelectorTest { 134 public: 135 virtual void SetUpInProcessBrowserTestFixture() OVERRIDE { 136 SSLClientCertificateSelectorTest::SetUpInProcessBrowserTestFixture(); 137 138 cert_request_info_1_ = new net::SSLCertRequestInfo; 139 cert_request_info_1_->host_and_port = net::HostPortPair("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_); 142 143 cert_request_info_2_ = new net::SSLCertRequestInfo; 144 cert_request_info_2_->host_and_port = net::HostPortPair("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_); 147 } 148 149 virtual void SetUpOnMainThread() OVERRIDE { 150 // Also calls SetUpOnIOThread. 151 SSLClientCertificateSelectorTest::SetUpOnMainThread(); 152 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)); 160 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, 166 auth_requestor_1_)); 167 selector_1_->Init(); 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, 173 auth_requestor_2_)); 174 selector_2_->Init(); 175 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()); 179 } 180 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(); 184 185 auth_requestor_1_ = new StrictMock<SSLClientAuthRequestorMock>( 186 url_request_1_, 187 cert_request_info_1_); 188 auth_requestor_2_ = new StrictMock<SSLClientAuthRequestorMock>( 189 url_request_2_, 190 cert_request_info_2_); 191 192 SSLClientCertificateSelectorTest::SetUpOnIOThread(); 193 } 194 195 virtual void TearDownOnMainThread() OVERRIDE { 196 auth_requestor_2_ = NULL; 197 auth_requestor_1_ = NULL; 198 SSLClientCertificateSelectorTest::TearDownOnMainThread(); 199 } 200 201 virtual void CleanUpOnIOThread() OVERRIDE { 202 delete url_request_1_; 203 delete url_request_2_; 204 SSLClientCertificateSelectorTest::CleanUpOnIOThread(); 205 } 206 207 protected: 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_; 216}; 217 218class SSLClientCertificateSelectorMultiProfileTest 219 : public SSLClientCertificateSelectorTest { 220 public: 221 virtual void SetUpInProcessBrowserTestFixture() OVERRIDE { 222 SSLClientCertificateSelectorTest::SetUpInProcessBrowserTestFixture(); 223 224 cert_request_info_1_ = new net::SSLCertRequestInfo; 225 cert_request_info_1_->host_and_port = net::HostPortPair("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_); 228 } 229 230 virtual void SetUpOnMainThread() OVERRIDE { 231 browser_1_ = CreateIncognitoBrowser(); 232 url_request_context_getter_1_ = browser_1_->profile()->GetRequestContext(); 233 234 // Also calls SetUpOnIOThread. 235 SSLClientCertificateSelectorTest::SetUpOnMainThread(); 236 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, 242 auth_requestor_1_)); 243 selector_1_->Init(); 244 245 EXPECT_EQ(mit_davidben_cert_.get(), selector_1_->GetSelectedCert()); 246 } 247 248 virtual void SetUpOnIOThread() OVERRIDE { 249 url_request_1_ = MakeURLRequest(url_request_context_getter_1_).release(); 250 251 auth_requestor_1_ = new StrictMock<SSLClientAuthRequestorMock>( 252 url_request_1_, 253 cert_request_info_1_); 254 255 SSLClientCertificateSelectorTest::SetUpOnIOThread(); 256 } 257 258 virtual void TearDownOnMainThread() OVERRIDE { 259 auth_requestor_1_ = NULL; 260 SSLClientCertificateSelectorTest::TearDownOnMainThread(); 261 } 262 263 virtual void CleanUpOnIOThread() OVERRIDE { 264 delete url_request_1_; 265 SSLClientCertificateSelectorTest::CleanUpOnIOThread(); 266 } 267 268 protected: 269 Browser* browser_1_; 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_; 275}; 276 277#if defined(OS_LINUX) && !defined(OS_CHROMEOS) && defined(USE_AURA) 278// TODO(erg): linux_aura bringup: http://crbug.com/163931 279#define MAYBE_SelectNone DISABLED_SelectNone 280#else 281#define MAYBE_SelectNone SelectNone 282#endif 283 284 285IN_PROC_BROWSER_TEST_F(SSLClientCertificateSelectorTest, MAYBE_SelectNone) { 286 EXPECT_CALL(*auth_requestor_, CertificateSelected(NULL)); 287 288 // Let the mock get checked on destruction. 289} 290 291// http://crbug.com/121007 292IN_PROC_BROWSER_TEST_F(SSLClientCertificateSelectorTest, DISABLED_Escape) { 293 EXPECT_CALL(*auth_requestor_, CertificateSelected(NULL)); 294 295 EXPECT_TRUE(ui_test_utils::SendKeyPressSync( 296 browser(), ui::VKEY_ESCAPE, false, false, false, false)); 297 298 Mock::VerifyAndClear(auth_requestor_.get()); 299} 300 301// Flaky, http://crbug.com/103534 . 302IN_PROC_BROWSER_TEST_F(SSLClientCertificateSelectorTest, 303 DISABLED_SelectDefault) { 304 EXPECT_CALL(*auth_requestor_, CertificateSelected(mit_davidben_cert_.get())); 305 306 EXPECT_TRUE(ui_test_utils::SendKeyPressSync( 307 browser(), ui::VKEY_RETURN, false, false, false, false)); 308 309 Mock::VerifyAndClear(auth_requestor_.get()); 310} 311 312// http://crbug.com/121007 313IN_PROC_BROWSER_TEST_F(SSLClientCertificateSelectorMultiTabTest, 314 DISABLED_Escape) { 315 // auth_requestor_1_ should get selected automatically by the 316 // SSLClientAuthObserver when selector_2_ is accepted, since both 1 & 2 have 317 // the same host:port. 318 EXPECT_CALL(*auth_requestor_1_, CertificateSelected(NULL)); 319 EXPECT_CALL(*auth_requestor_2_, CertificateSelected(NULL)); 320 321 EXPECT_TRUE(ui_test_utils::SendKeyPressSync( 322 browser(), ui::VKEY_ESCAPE, false, false, false, false)); 323 324 Mock::VerifyAndClear(auth_requestor_.get()); 325 Mock::VerifyAndClear(auth_requestor_1_.get()); 326 Mock::VerifyAndClear(auth_requestor_2_.get()); 327 328 // Now let the default selection for auth_requestor_ mock get checked on 329 // destruction. 330 EXPECT_CALL(*auth_requestor_, CertificateSelected(NULL)); 331} 332 333// http://crbug.com/121007 334IN_PROC_BROWSER_TEST_F(SSLClientCertificateSelectorMultiTabTest, 335 DISABLED_SelectSecond) { 336 // auth_requestor_1_ should get selected automatically by the 337 // SSLClientAuthObserver when selector_2_ is accepted, since both 1 & 2 have 338 // the same host:port. 339 EXPECT_CALL(*auth_requestor_1_, 340 CertificateSelected(foaf_me_chromium_test_cert_.get())); 341 EXPECT_CALL(*auth_requestor_2_, 342 CertificateSelected(foaf_me_chromium_test_cert_.get())); 343 344 EXPECT_TRUE(ui_test_utils::SendKeyPressSync( 345 browser(), ui::VKEY_DOWN, false, false, false, false)); 346 347 EXPECT_EQ(mit_davidben_cert_.get(), selector_->GetSelectedCert()); 348 EXPECT_EQ(mit_davidben_cert_.get(), selector_1_->GetSelectedCert()); 349 EXPECT_EQ(foaf_me_chromium_test_cert_.get(), selector_2_->GetSelectedCert()); 350 351 EXPECT_TRUE(ui_test_utils::SendKeyPressSync( 352 browser(), ui::VKEY_RETURN, false, false, false, false)); 353 354 Mock::VerifyAndClear(auth_requestor_.get()); 355 Mock::VerifyAndClear(auth_requestor_1_.get()); 356 Mock::VerifyAndClear(auth_requestor_2_.get()); 357 358 // Now let the default selection for auth_requestor_ mock get checked on 359 // destruction. 360 EXPECT_CALL(*auth_requestor_, CertificateSelected(NULL)); 361} 362 363// http://crbug.com/103529 364IN_PROC_BROWSER_TEST_F(SSLClientCertificateSelectorMultiProfileTest, 365 DISABLED_Escape) { 366 EXPECT_CALL(*auth_requestor_1_, CertificateSelected(NULL)); 367 368 EXPECT_TRUE(ui_test_utils::SendKeyPressSync( 369 browser_1_, ui::VKEY_ESCAPE, false, false, false, false)); 370 371 Mock::VerifyAndClear(auth_requestor_.get()); 372 Mock::VerifyAndClear(auth_requestor_1_.get()); 373 374 // Now let the default selection for auth_requestor_ mock get checked on 375 // destruction. 376 EXPECT_CALL(*auth_requestor_, CertificateSelected(NULL)); 377} 378 379// http://crbug.com/103534 380IN_PROC_BROWSER_TEST_F(SSLClientCertificateSelectorMultiProfileTest, 381 DISABLED_SelectDefault) { 382 EXPECT_CALL(*auth_requestor_1_, 383 CertificateSelected(mit_davidben_cert_.get())); 384 385 EXPECT_TRUE(ui_test_utils::SendKeyPressSync( 386 browser_1_, ui::VKEY_RETURN, false, false, false, false)); 387 388 Mock::VerifyAndClear(auth_requestor_.get()); 389 Mock::VerifyAndClear(auth_requestor_1_.get()); 390 391 // Now let the default selection for auth_requestor_ mock get checked on 392 // destruction. 393 EXPECT_CALL(*auth_requestor_, CertificateSelected(NULL)); 394} 395