| OLD | NEW | 
| (Empty) |  | 
 |    1 // Copyright (c) 2010 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 "chrome/browser/ssl_client_certificate_selector.h" | 
 |    6  | 
 |    7 #import <SecurityInterface/SFChooseIdentityPanel.h> | 
 |    8  | 
 |    9 #include <vector> | 
 |   10  | 
 |   11 #import "app/l10n_util_mac.h" | 
 |   12 #include "base/logging.h" | 
 |   13 #include "base/ref_counted.h" | 
 |   14 #include "base/scoped_cftyperef.h" | 
 |   15 #import "base/scoped_nsobject.h" | 
 |   16 #include "base/string_util.h" | 
 |   17 #include "base/sys_string_conversions.h" | 
 |   18 #include "chrome/browser/chrome_thread.h" | 
 |   19 #include "chrome/browser/ssl/ssl_client_auth_handler.h" | 
 |   20 #include "grit/generated_resources.h" | 
 |   21 #include "net/base/x509_certificate.h" | 
 |   22  | 
 |   23 @interface SSLClientCertificateSelectorCocoa : NSObject { | 
 |   24  @private | 
 |   25   // The handler to report back to. | 
 |   26   scoped_refptr<SSLClientAuthHandler> handler_; | 
 |   27   // The certificate request we serve. | 
 |   28   scoped_refptr<net::SSLCertRequestInfo> certRequestInfo_; | 
 |   29   // The list of identities offered to the user. | 
 |   30   scoped_nsobject<NSMutableArray> identities_; | 
 |   31   // The corresponding list of certificates. | 
 |   32   std::vector<scoped_refptr<net::X509Certificate> > certificates_; | 
 |   33   // The panel we display. | 
 |   34   scoped_nsobject<SFChooseIdentityPanel> panel_; | 
 |   35 } | 
 |   36  | 
 |   37 - (id)initWithHandler:(SSLClientAuthHandler*)handler | 
 |   38       certRequestInfo:(net::SSLCertRequestInfo*)certRequestInfo; | 
 |   39 - (void)displayDialog:(gfx::NativeWindow)parent; | 
 |   40 @end | 
 |   41  | 
 |   42 namespace browser { | 
 |   43  | 
 |   44 void ShowSSLClientCertificateSelector( | 
 |   45     gfx::NativeWindow parent, | 
 |   46     net::SSLCertRequestInfo* cert_request_info, | 
 |   47     SSLClientAuthHandler* delegate) { | 
 |   48   DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI)); | 
 |   49   SSLClientCertificateSelectorCocoa* selector = | 
 |   50       [[[SSLClientCertificateSelectorCocoa alloc] | 
 |   51           initWithHandler:delegate | 
 |   52           certRequestInfo:cert_request_info] autorelease]; | 
 |   53   [selector displayDialog:parent]; | 
 |   54 } | 
 |   55  | 
 |   56 }  // namespace browser | 
 |   57  | 
 |   58 @implementation SSLClientCertificateSelectorCocoa | 
 |   59  | 
 |   60 - (id)initWithHandler:(SSLClientAuthHandler*)handler | 
 |   61       certRequestInfo:(net::SSLCertRequestInfo*)certRequestInfo { | 
 |   62   DCHECK(handler); | 
 |   63   DCHECK(certRequestInfo); | 
 |   64   if ((self = [super init])) { | 
 |   65     handler_ = handler; | 
 |   66     certRequestInfo_ = certRequestInfo; | 
 |   67   } | 
 |   68   return self; | 
 |   69 } | 
 |   70  | 
 |   71 - (void)sheetDidEnd:(NSWindow*)parent | 
 |   72          returnCode:(NSInteger)returnCode | 
 |   73             context:(void*)context { | 
 |   74   net::X509Certificate* cert = NULL; | 
 |   75  | 
 |   76   if (returnCode == NSFileHandlingPanelOKButton) { | 
 |   77     NSUInteger index = [identities_ indexOfObject:(id)[panel_ identity]]; | 
 |   78     DCHECK(index != NSNotFound); | 
 |   79     cert = certificates_[index]; | 
 |   80   } | 
 |   81  | 
 |   82   // Finally, tell the backend which identity (or none) the user selected. | 
 |   83   handler_->CertificateSelected(cert); | 
 |   84   // Clean up. The retain occurred just before the sheet opened. | 
 |   85   [self release]; | 
 |   86 } | 
 |   87  | 
 |   88 - (void)displayDialog:(gfx::NativeWindow)parent { | 
 |   89   DCHECK(!panel_.get()); | 
 |   90   // Create an array of CFIdentityRefs for the certificates: | 
 |   91   size_t numCerts = certRequestInfo_->client_certs.size(); | 
 |   92   identities_.reset([[NSMutableArray alloc] initWithCapacity:numCerts]); | 
 |   93   for (size_t i = 0; i < numCerts; ++i) { | 
 |   94     SecCertificateRef cert; | 
 |   95     cert = certRequestInfo_->client_certs[i]->os_cert_handle(); | 
 |   96     SecIdentityRef identity; | 
 |   97     if (SecIdentityCreateWithCertificate(NULL, cert, &identity) == noErr) { | 
 |   98       [identities_ addObject:(id)identity]; | 
 |   99       CFRelease(identity); | 
 |  100       certificates_.push_back(certRequestInfo_->client_certs[i]); | 
 |  101     } | 
 |  102   } | 
 |  103  | 
 |  104   // Get the message to display: | 
 |  105   NSString* title = l10n_util::GetNSString(IDS_CLIENT_CERT_DIALOG_TITLE); | 
 |  106   NSString* message = l10n_util::GetNSStringF( | 
 |  107       IDS_CLIENT_CERT_DIALOG_TEXT, | 
 |  108       ASCIIToUTF16(certRequestInfo_->host_and_port)); | 
 |  109  | 
 |  110   // Create and set up a system choose-identity panel. | 
 |  111   panel_.reset([[SFChooseIdentityPanel alloc] init]); | 
 |  112   NSString* domain = base::SysUTF8ToNSString( | 
 |  113       "https://" + certRequestInfo_->host_and_port); | 
 |  114   // Setting the domain causes the dialog to record the preferred | 
 |  115   // identity in the system keychain. | 
 |  116   [panel_ setDomain:domain]; | 
 |  117   [panel_ setInformativeText:message]; | 
 |  118   [panel_ setDefaultButtonTitle:l10n_util::GetNSString(IDS_OK)]; | 
 |  119   [panel_ setAlternateButtonTitle:l10n_util::GetNSString(IDS_CANCEL)]; | 
 |  120   SecPolicyRef sslPolicy; | 
 |  121   if (net::X509Certificate::CreateSSLClientPolicy(&sslPolicy) == noErr) { | 
 |  122     [panel_ setPolicies:(id)sslPolicy]; | 
 |  123     CFRelease(sslPolicy); | 
 |  124   } | 
 |  125  | 
 |  126   // Increase the retain count to keep |self| alive while the sheet | 
 |  127   // runs. -sheetDidEnd:returnCode:context: will release the | 
 |  128   // additional reference. | 
 |  129   [self retain]; | 
 |  130   if (parent) { | 
 |  131     // Open the cert panel as a sheet on the browser window. | 
 |  132     [panel_ beginSheetForWindow:parent | 
 |  133                   modalDelegate:self | 
 |  134                  didEndSelector:@selector(sheetDidEnd:returnCode:context:) | 
 |  135                     contextInfo:nil | 
 |  136                     identities:identities_ | 
 |  137                        message:title]; | 
 |  138   } else { | 
 |  139     // No available browser window, so run independently as a (blocking) dialog. | 
 |  140     int returnCode = [panel_ runModalForIdentities:identities_ message:title]; | 
 |  141     [self sheetDidEnd:panel_ returnCode:returnCode context:nil]; | 
 |  142   } | 
 |  143 } | 
 |  144  | 
 |  145 @end | 
| OLD | NEW |