| 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 a8d7912f5204808919e499b1910929f09ab09571..54ff89123d38624b0cf371dea480cbe7c67dc412 100644
|
| --- a/chrome/browser/ui/cocoa/ssl_client_certificate_selector_cocoa.mm
|
| +++ b/chrome/browser/ui/cocoa/ssl_client_certificate_selector_cocoa.mm
|
| @@ -14,7 +14,9 @@
|
| #include "chrome/browser/ssl/ssl_client_auth_observer.h"
|
| #import "chrome/browser/ui/cocoa/constrained_window/constrained_window_mac.h"
|
| #include "chrome/grit/generated_resources.h"
|
| +#include "components/web_modal/popup_manager.h"
|
| #include "content/public/browser/browser_thread.h"
|
| +#include "content/public/browser/client_certificate_delegate.h"
|
| #include "content/public/browser/web_contents.h"
|
| #include "net/cert/x509_certificate.h"
|
| #include "net/cert/x509_util_mac.h"
|
| @@ -42,11 +44,12 @@ class SSLClientAuthObserverCocoaBridge : public SSLClientAuthObserver,
|
| SSLClientAuthObserverCocoaBridge(
|
| const content::BrowserContext* browser_context,
|
| net::SSLCertRequestInfo* cert_request_info,
|
| - const chrome::SelectCertificateCallback& callback,
|
| + scoped_ptr<content::ClientCertificateDelegate> delegate,
|
| SSLClientCertificateSelectorCocoa* controller)
|
| - : SSLClientAuthObserver(browser_context, cert_request_info, callback),
|
| - controller_(controller) {
|
| - }
|
| + : SSLClientAuthObserver(browser_context,
|
| + cert_request_info,
|
| + delegate.Pass()),
|
| + controller_(controller) {}
|
|
|
| // SSLClientAuthObserver implementation:
|
| void OnCertSelectedByNotification() override {
|
| @@ -72,14 +75,22 @@ namespace chrome {
|
| void ShowSSLClientCertificateSelector(
|
| content::WebContents* contents,
|
| net::SSLCertRequestInfo* cert_request_info,
|
| - const SelectCertificateCallback& callback) {
|
| + scoped_ptr<content::ClientCertificateDelegate> delegate) {
|
| DCHECK_CURRENTLY_ON(BrowserThread::UI);
|
| +
|
| + // Not all WebContentses can show modal dialogs.
|
| + //
|
| + // TODO(davidben): Move this hook to the WebContentsDelegate and only try to
|
| + // show a dialog in Browser's implementation. https://crbug.com/456255
|
| + if (web_modal::PopupManager::FromWebContents(contents) == nullptr)
|
| + return;
|
| +
|
| // The dialog manages its own lifetime.
|
| SSLClientCertificateSelectorCocoa* selector =
|
| [[SSLClientCertificateSelectorCocoa alloc]
|
| initWithBrowserContext:contents->GetBrowserContext()
|
| certRequestInfo:cert_request_info
|
| - callback:callback];
|
| + delegate:delegate.Pass()];
|
| [selector displayForWebContents:contents];
|
| }
|
|
|
| @@ -88,13 +99,14 @@ void ShowSSLClientCertificateSelector(
|
| @implementation SSLClientCertificateSelectorCocoa
|
|
|
| - (id)initWithBrowserContext:(const content::BrowserContext*)browserContext
|
| - certRequestInfo:(net::SSLCertRequestInfo*)certRequestInfo
|
| - callback:(const chrome::SelectCertificateCallback&)callback {
|
| + certRequestInfo:(net::SSLCertRequestInfo*)certRequestInfo
|
| + delegate:(scoped_ptr<content::ClientCertificateDelegate>)
|
| + delegate {
|
| DCHECK(browserContext);
|
| DCHECK(certRequestInfo);
|
| if ((self = [super init])) {
|
| observer_.reset(new SSLClientAuthObserverCocoaBridge(
|
| - browserContext, certRequestInfo, callback, self));
|
| + browserContext, certRequestInfo, delegate.Pass(), self));
|
| }
|
| return self;
|
| }
|
| @@ -113,12 +125,16 @@ void ShowSSLClientCertificateSelector(
|
| NOTREACHED();
|
| }
|
|
|
| - // Finally, tell the backend which identity (or none) the user selected.
|
| - observer_->StopObserving();
|
| - observer_->CertificateSelected(cert);
|
| + if (!closePending_) {
|
| + // If |closePending_| is already set, |closeSheetWithAnimation:| was called
|
| + // already to cancel the selection rather than continue with no
|
| + // certificate. Otherwise, tell the backend which identity (or none) the
|
| + // user selected.
|
| + userResponded_ = YES;
|
| + observer_->CertificateSelected(cert);
|
|
|
| - if (!closePending_)
|
| constrainedWindow_->CloseWebContentsModalDialog();
|
| + }
|
| }
|
|
|
| - (void)displayForWebContents:(content::WebContents*)webContents {
|
| @@ -184,6 +200,14 @@ void ShowSSLClientCertificateSelector(
|
| }
|
|
|
| - (void)closeSheetWithAnimation:(BOOL)withAnimation {
|
| + if (!userResponded_) {
|
| + // If the sheet is closed by closing the tab rather than the user explicitly
|
| + // hitting Cancel, |closeSheetWithAnimation:| gets called before
|
| + // |sheetDidEnd:|. In this case, the selection should be canceled rather
|
| + // than continue with no certificate. The |returnCode| parameter to
|
| + // |sheetDidEnd:| is the same in both cases.
|
| + observer_->CancelCertificateSelection();
|
| + }
|
| closePending_ = YES;
|
| overlayWindow_.reset();
|
| // Closing the sheet using -[NSApp endSheet:] doesn't work so use the private
|
|
|