Chromium Code Reviews| Index: chrome/browser/ui/cocoa/ssl_client_certificate_selector_cocoa.mm |
| diff --git a/chrome/browser/ui/cocoa/ssl_client_certificate_selector_cocoa.mm b/chrome/browser/ui/cocoa/ssl_client_certificate_selector_cocoa.mm |
| index 2143bfe73cfab2baec6bd910aff7db19becc68a8..ceb4c888005af0d8edaf8a50ddf5c436d593de3b 100644 |
| --- a/chrome/browser/ui/cocoa/ssl_client_certificate_selector_cocoa.mm |
| +++ b/chrome/browser/ui/cocoa/ssl_client_certificate_selector_cocoa.mm |
| @@ -72,6 +72,13 @@ class SSLClientAuthObserverCocoaBridge : public SSLClientAuthObserver, |
| afterDelay:0]; |
| } |
| + void GotPrivateKey( |
| + base::scoped_nsobject<SSLClientCertificateSelectorCocoa> controller_ref, |
| + net::X509Certificate* cert, |
| + scoped_refptr<net::SSLPrivateKey> private_key) { |
| + CertificateSelected(cert, private_key.get()); |
| + } |
| + |
| private: |
| SSLClientCertificateSelectorCocoa* controller_; // weak |
| }; |
| @@ -81,7 +88,7 @@ namespace chrome { |
| void ShowSSLClientCertificateSelector( |
| content::WebContents* contents, |
| net::SSLCertRequestInfo* cert_request_info, |
| - net::CertificateList client_certs, |
| + net::ClientCertIdentityList client_certs, |
| std::unique_ptr<content::ClientCertificateDelegate> delegate) { |
| DCHECK_CURRENTLY_ON(BrowserThread::UI); |
| @@ -177,13 +184,13 @@ void ClearTableViewDataSourcesIfNeeded(NSWindow*) {} |
| - (void)sheetDidEnd:(NSWindow*)sheet |
| returnCode:(NSInteger)returnCode |
| context:(void*)context { |
| - net::X509Certificate* cert = NULL; |
| + net::ClientCertIdentity* cert = nullptr; |
| if (returnCode == NSFileHandlingPanelOKButton) { |
| - CFRange range = CFRangeMake(0, CFArrayGetCount(identities_)); |
| + CFRange range = CFRangeMake(0, CFArrayGetCount(sec_identities_)); |
| CFIndex index = |
| - CFArrayGetFirstIndexOfValue(identities_, range, [panel_ identity]); |
| + CFArrayGetFirstIndexOfValue(sec_identities_, range, [panel_ identity]); |
| if (index != -1) |
| - cert = certificates_[index].get(); |
| + cert = cert_identities_[index].get(); |
| else |
| NOTREACHED(); |
| } |
| @@ -197,30 +204,40 @@ void ClearTableViewDataSourcesIfNeeded(NSWindow*) {} |
| // certificate. Otherwise, tell the backend which identity (or none) the |
| // user selected. |
| userResponded_ = YES; |
| - observer_->CertificateSelected(cert); |
| + |
| + // Remove the observer before we try acquiring private key, otherwise we |
| + // might act on a notification while waiting for the callback, causing us |
| + // to delete ourself before the callback gets called. |
| + observer_->StopObserving(); |
| + |
| + if (cert) { |
| + // Pass a scoped_nsobject handle for |self| to ensure |observer_| and |
| + // |cert_identities_| stay alive until the private key is acquired. |
| + cert->AcquirePrivateKey( |
| + base::Bind(&SSLClientAuthObserverCocoaBridge::GotPrivateKey, |
| + base::Unretained(observer_.get()), |
| + base::scoped_nsobject<SSLClientCertificateSelectorCocoa>( |
| + [self retain]), |
| + base::Unretained(cert->certificate()))); |
|
davidben
2017/06/07 23:06:16
Optional: It's a little odd here that you're calli
mattm
2017/06/08 21:47:55
Yeah, I think that makes sense. If this code is al
|
| + } else { |
| + observer_->CertificateSelected(nullptr, nullptr); |
| + } |
| constrainedWindow_->CloseWebContentsModalDialog(); |
| } |
| } |
| - (void)displayForWebContents:(content::WebContents*)webContents |
| - clientCerts:(net::CertificateList)inputClientCerts { |
| + clientCerts:(net::ClientCertIdentityList)inputClientCerts { |
| + cert_identities_ = std::move(inputClientCerts); |
| // Create an array of CFIdentityRefs for the certificates: |
| - size_t numCerts = inputClientCerts.size(); |
| - identities_.reset(CFArrayCreateMutable( |
| - kCFAllocatorDefault, numCerts, &kCFTypeArrayCallBacks)); |
| + size_t numCerts = cert_identities_.size(); |
| + sec_identities_.reset(CFArrayCreateMutable(kCFAllocatorDefault, numCerts, |
| + &kCFTypeArrayCallBacks)); |
| for (size_t i = 0; i < numCerts; ++i) { |
| - base::ScopedCFTypeRef<SecCertificateRef> cert( |
| - net::x509_util::CreateSecCertificateFromX509Certificate( |
| - inputClientCerts[i].get())); |
| - if (!cert) |
| - continue; |
| - SecIdentityRef identity; |
| - if (SecIdentityCreateWithCertificate(NULL, cert, &identity) == noErr) { |
| - CFArrayAppendValue(identities_, identity); |
| - CFRelease(identity); |
| - certificates_.push_back(inputClientCerts[i]); |
| - } |
| + DCHECK(cert_identities_[i]->sec_identity_ref()); |
| + CFArrayAppendValue(sec_identities_, |
| + cert_identities_[i]->sec_identity_ref()); |
| } |
| // Get the message to display: |
| @@ -265,7 +282,7 @@ void ClearTableViewDataSourcesIfNeeded(NSWindow*) {} |
| modalDelegate:self |
| didEndSelector:@selector(sheetDidEnd:returnCode:context:) |
| contextInfo:NULL |
| - identities:base::mac::CFToNSCast(identities_) |
| + identities:base::mac::CFToNSCast(sec_identities_) |
| message:title]; |
| } |