Index: chrome/browser/ui/cocoa/ssl_client_certificate_selector_cocoa_browsertest.mm |
diff --git a/chrome/browser/ui/cocoa/ssl_client_certificate_selector_cocoa_browsertest.mm b/chrome/browser/ui/cocoa/ssl_client_certificate_selector_cocoa_browsertest.mm |
index b0798358541aa99ff25c65f686725c7c02182bde..f9bdcee2029a9aca4f42e6fc3e82d2c4c88afb54 100644 |
--- a/chrome/browser/ui/cocoa/ssl_client_certificate_selector_cocoa_browsertest.mm |
+++ b/chrome/browser/ui/cocoa/ssl_client_certificate_selector_cocoa_browsertest.mm |
@@ -20,39 +20,56 @@ |
#include "content/public/browser/web_contents.h" |
#include "content/public/test/test_utils.h" |
#include "net/cert/x509_certificate.h" |
+#include "net/ssl/client_cert_identity_mac.h" |
+#include "net/ssl/ssl_private_key_test_util.h" |
#include "net/test/cert_test_util.h" |
+#include "net/test/keychain_test_util_mac.h" |
#include "net/test/test_data_directory.h" |
#import "testing/gtest_mac.h" |
#include "ui/base/cocoa/window_size_constants.h" |
using web_modal::WebContentsModalDialogManager; |
+@interface SFChooseIdentityPanel (SystemPrivate) |
+// A system-private interface that dismisses a panel whose sheet was started by |
+// -beginSheetForWindow:modalDelegate:didEndSelector:contextInfo:identities:message: |
+// as though the user clicked the button identified by returnCode. Verified |
+// present in 10.5 through 10.12. |
+- (void)_dismissWithCode:(NSInteger)code; |
+@end |
+ |
namespace { |
+struct TestClientCertificateDelegateResults { |
+ bool destroyed = false; |
+ bool continue_with_certificate_called = false; |
+ scoped_refptr<net::X509Certificate> cert; |
+ scoped_refptr<net::SSLPrivateKey> key; |
+}; |
+ |
class TestClientCertificateDelegate |
: public content::ClientCertificateDelegate { |
public: |
// Creates a ClientCertificateDelegate that sets |*destroyed| to true on |
// destruction. |
- explicit TestClientCertificateDelegate(bool* destroyed) |
- : destroyed_(destroyed) {} |
+ explicit TestClientCertificateDelegate( |
+ TestClientCertificateDelegateResults* results) |
+ : results_(results) {} |
- ~TestClientCertificateDelegate() override { |
- if (destroyed_ != nullptr) |
- *destroyed_ = true; |
- } |
+ ~TestClientCertificateDelegate() override { results_->destroyed = true; } |
// content::ClientCertificateDelegate. |
- void ContinueWithCertificate(net::X509Certificate* cert) override { |
- // TODO(davidben): Add a test which explicitly tests selecting a |
- // certificate, or selecting no certificate, since closing the dialog |
- // (normally by closing the tab) is not the same as explicitly selecting no |
- // certificate. |
- ADD_FAILURE() << "Certificate selected"; |
+ void ContinueWithCertificate(scoped_refptr<net::X509Certificate> cert, |
+ scoped_refptr<net::SSLPrivateKey> key) override { |
+ EXPECT_FALSE(results_->continue_with_certificate_called); |
+ results_->cert = cert; |
+ results_->key = key; |
+ results_->continue_with_certificate_called = true; |
+ // TODO(mattm): Add a test of selecting the 2nd certificate (if possible). |
} |
private: |
- bool* destroyed_; |
+ TestClientCertificateDelegateResults* results_; |
DISALLOW_COPY_AND_ASSIGN(TestClientCertificateDelegate); |
}; |
@@ -67,12 +84,16 @@ class SSLClientCertificateSelectorCocoaTest |
// InProcessBrowserTest: |
void SetUpInProcessBrowserTestFixture() override; |
- net::CertificateList GetTestCertificateList(); |
+ net::ClientCertIdentityList GetTestCertificateList(); |
- private: |
- scoped_refptr<net::X509Certificate> mit_davidben_cert_; |
- scoped_refptr<net::X509Certificate> foaf_me_chromium_test_cert_; |
- net::CertificateList client_cert_list_; |
+ protected: |
+ scoped_refptr<net::X509Certificate> client_cert1_; |
+ scoped_refptr<net::X509Certificate> client_cert2_; |
+ std::string pkcs8_key1_; |
+ std::string pkcs8_key2_; |
+ net::ScopedTestKeychain scoped_keychain_; |
+ base::ScopedCFTypeRef<SecIdentityRef> sec_identity1_; |
+ base::ScopedCFTypeRef<SecIdentityRef> sec_identity2_; |
}; |
SSLClientCertificateSelectorCocoaTest:: |
@@ -83,40 +104,50 @@ void SSLClientCertificateSelectorCocoaTest::SetUpInProcessBrowserTestFixture() { |
base::FilePath certs_dir = net::GetTestCertsDirectory(); |
- mit_davidben_cert_ = net::ImportCertFromFile(certs_dir, "mit.davidben.der"); |
- ASSERT_TRUE(mit_davidben_cert_.get()); |
+ client_cert1_ = net::ImportCertFromFile(certs_dir, "client_1.pem"); |
+ ASSERT_TRUE(client_cert1_); |
+ client_cert2_ = net::ImportCertFromFile(certs_dir, "client_2.pem"); |
+ ASSERT_TRUE(client_cert2_); |
+ |
+ ASSERT_TRUE(base::ReadFileToString(certs_dir.AppendASCII("client_1.pk8"), |
+ &pkcs8_key1_)); |
+ ASSERT_TRUE(base::ReadFileToString(certs_dir.AppendASCII("client_2.pk8"), |
+ &pkcs8_key2_)); |
- foaf_me_chromium_test_cert_ = |
- net::ImportCertFromFile(certs_dir, "foaf.me.chromium-test-cert.der"); |
- ASSERT_TRUE(foaf_me_chromium_test_cert_.get()); |
+ ASSERT_TRUE(scoped_keychain_.Initialize()); |
- client_cert_list_.push_back(mit_davidben_cert_); |
- client_cert_list_.push_back(foaf_me_chromium_test_cert_); |
+ sec_identity1_ = net::ImportCertAndKeyToKeychain( |
+ client_cert1_.get(), pkcs8_key1_, scoped_keychain_.keychain()); |
+ ASSERT_TRUE(sec_identity1_); |
+ sec_identity2_ = net::ImportCertAndKeyToKeychain( |
+ client_cert2_.get(), pkcs8_key2_, scoped_keychain_.keychain()); |
+ ASSERT_TRUE(sec_identity2_); |
} |
-net::CertificateList |
+net::ClientCertIdentityList |
SSLClientCertificateSelectorCocoaTest::GetTestCertificateList() { |
- return client_cert_list_; |
+ net::ClientCertIdentityList client_cert_list; |
+ client_cert_list.push_back(base::MakeUnique<net::ClientCertIdentityMac>( |
+ client_cert1_, base::ScopedCFTypeRef<SecIdentityRef>(sec_identity1_))); |
+ client_cert_list.push_back(base::MakeUnique<net::ClientCertIdentityMac>( |
+ client_cert2_, base::ScopedCFTypeRef<SecIdentityRef>(sec_identity2_))); |
+ return client_cert_list; |
} |
-// Flaky on 10.7; crbug.com/313243 |
-IN_PROC_BROWSER_TEST_F(SSLClientCertificateSelectorCocoaTest, DISABLED_Basic) { |
- // TODO(kbr): re-enable: http://crbug.com/222296 |
- return; |
- |
+IN_PROC_BROWSER_TEST_F(SSLClientCertificateSelectorCocoaTest, Basic) { |
content::WebContents* web_contents = |
browser()->tab_strip_model()->GetActiveWebContents(); |
WebContentsModalDialogManager* web_contents_modal_dialog_manager = |
WebContentsModalDialogManager::FromWebContents(web_contents); |
EXPECT_FALSE(web_contents_modal_dialog_manager->IsDialogActive()); |
- bool destroyed = false; |
+ TestClientCertificateDelegateResults results; |
SSLClientCertificateSelectorCocoa* selector = [ |
[SSLClientCertificateSelectorCocoa alloc] |
initWithBrowserContext:web_contents->GetBrowserContext() |
certRequestInfo:auth_requestor_->cert_request_info_.get() |
- delegate:base::WrapUnique(new TestClientCertificateDelegate( |
- &destroyed))]; |
+ delegate:base::WrapUnique( |
+ new TestClientCertificateDelegate(&results))]; |
[selector displayForWebContents:web_contents |
clientCerts:GetTestCertificateList()]; |
content::RunAllPendingInMessageLoop(); |
@@ -129,19 +160,94 @@ IN_PROC_BROWSER_TEST_F(SSLClientCertificateSelectorCocoaTest, DISABLED_Basic) { |
content::RunAllPendingInMessageLoop(); |
EXPECT_FALSE(web_contents_modal_dialog_manager->IsDialogActive()); |
- EXPECT_TRUE(destroyed); |
+ EXPECT_TRUE(results.destroyed); |
+ EXPECT_FALSE(results.continue_with_certificate_called); |
+} |
+ |
+IN_PROC_BROWSER_TEST_F(SSLClientCertificateSelectorCocoaTest, Cancel) { |
+ content::WebContents* web_contents = |
+ browser()->tab_strip_model()->GetActiveWebContents(); |
+ WebContentsModalDialogManager* web_contents_modal_dialog_manager = |
+ WebContentsModalDialogManager::FromWebContents(web_contents); |
+ EXPECT_FALSE(web_contents_modal_dialog_manager->IsDialogActive()); |
+ |
+ TestClientCertificateDelegateResults results; |
+ SSLClientCertificateSelectorCocoa* selector = [ |
+ [SSLClientCertificateSelectorCocoa alloc] |
+ initWithBrowserContext:web_contents->GetBrowserContext() |
+ certRequestInfo:auth_requestor_->cert_request_info_.get() |
+ delegate:base::WrapUnique( |
+ new TestClientCertificateDelegate(&results))]; |
+ [selector displayForWebContents:web_contents |
+ clientCerts:GetTestCertificateList()]; |
+ content::RunAllPendingInMessageLoop(); |
+ EXPECT_TRUE([selector panel]); |
+ EXPECT_TRUE(web_contents_modal_dialog_manager->IsDialogActive()); |
+ |
+ // Cancel the selector. Dunno if there is a better way to do this. |
+ [[selector panel] _dismissWithCode:NSFileHandlingPanelCancelButton]; |
+ content::RunAllPendingInMessageLoop(); |
+ EXPECT_FALSE(web_contents_modal_dialog_manager->IsDialogActive()); |
+ |
+ // ContinueWithCertificate(nullptr, nullptr) should have been called. |
+ EXPECT_TRUE(results.destroyed); |
+ EXPECT_TRUE(results.continue_with_certificate_called); |
+ EXPECT_FALSE(results.cert); |
+ EXPECT_FALSE(results.key); |
+} |
+ |
+IN_PROC_BROWSER_TEST_F(SSLClientCertificateSelectorCocoaTest, Accept) { |
+ content::WebContents* web_contents = |
+ browser()->tab_strip_model()->GetActiveWebContents(); |
+ WebContentsModalDialogManager* web_contents_modal_dialog_manager = |
+ WebContentsModalDialogManager::FromWebContents(web_contents); |
+ EXPECT_FALSE(web_contents_modal_dialog_manager->IsDialogActive()); |
+ |
+ TestClientCertificateDelegateResults results; |
+ SSLClientCertificateSelectorCocoa* selector = [ |
+ [SSLClientCertificateSelectorCocoa alloc] |
+ initWithBrowserContext:web_contents->GetBrowserContext() |
+ certRequestInfo:auth_requestor_->cert_request_info_.get() |
+ delegate:base::WrapUnique( |
+ new TestClientCertificateDelegate(&results))]; |
+ [selector displayForWebContents:web_contents |
+ clientCerts:GetTestCertificateList()]; |
+ content::RunAllPendingInMessageLoop(); |
+ EXPECT_TRUE([selector panel]); |
+ EXPECT_TRUE(web_contents_modal_dialog_manager->IsDialogActive()); |
+ |
+ // Accept the selection. Dunno if there is a better way to do this. |
+ [[selector panel] _dismissWithCode:NSFileHandlingPanelOKButton]; |
+ content::RunAllPendingInMessageLoop(); |
+ EXPECT_FALSE(web_contents_modal_dialog_manager->IsDialogActive()); |
+ |
+ // The first cert in the list should have been selected. |
+ EXPECT_TRUE(results.destroyed); |
+ EXPECT_TRUE(results.continue_with_certificate_called); |
+ EXPECT_EQ(client_cert1_, results.cert); |
+ ASSERT_TRUE(results.key); |
+ |
+ // All Mac keys are expected to have the same hash preferences. |
+ std::vector<net::SSLPrivateKey::Hash> expected_hashes = { |
+ net::SSLPrivateKey::Hash::SHA512, net::SSLPrivateKey::Hash::SHA384, |
+ net::SSLPrivateKey::Hash::SHA256, net::SSLPrivateKey::Hash::SHA1, |
+ }; |
+ EXPECT_EQ(expected_hashes, results.key->GetDigestPreferences()); |
+ |
+ TestSSLPrivateKeyMatches(results.key.get(), pkcs8_key1_); |
} |
// Test that switching to another tab correctly hides the sheet. |
IN_PROC_BROWSER_TEST_F(SSLClientCertificateSelectorCocoaTest, HideShow) { |
content::WebContents* web_contents = |
browser()->tab_strip_model()->GetActiveWebContents(); |
+ TestClientCertificateDelegateResults results; |
SSLClientCertificateSelectorCocoa* selector = [ |
[SSLClientCertificateSelectorCocoa alloc] |
initWithBrowserContext:web_contents->GetBrowserContext() |
certRequestInfo:auth_requestor_->cert_request_info_.get() |
delegate:base::WrapUnique( |
- new TestClientCertificateDelegate(nullptr))]; |
+ new TestClientCertificateDelegate(&results))]; |
[selector displayForWebContents:web_contents |
clientCerts:GetTestCertificateList()]; |
content::RunAllPendingInMessageLoop(); |
@@ -160,6 +266,9 @@ IN_PROC_BROWSER_TEST_F(SSLClientCertificateSelectorCocoaTest, HideShow) { |
chrome::SelectNumberedTab(browser(), 0); |
EXPECT_EQ(1.0, [sheetWindow alphaValue]); |
EXPECT_FALSE([[selector overlayWindow] ignoresMouseEvents]); |
+ |
+ EXPECT_FALSE(results.destroyed); |
+ EXPECT_FALSE(results.continue_with_certificate_called); |
} |
@interface DeallocTrackingSSLClientCertificateSelectorCocoa |