tab_contents_ssl_helper.cc revision 21d179b334e59e9a3bfcaed4c4430bef1bc5759d
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/tab_contents/tab_contents_ssl_helper.h"
6
7#include "app/l10n_util.h"
8#include "app/resource_bundle.h"
9#include "base/basictypes.h"
10#include "base/string_number_conversions.h"
11#include "base/utf_string_conversions.h"
12#include "chrome/browser/certificate_viewer.h"
13#include "chrome/browser/ssl/ssl_add_cert_handler.h"
14#include "chrome/browser/ssl/ssl_client_auth_handler.h"
15#include "chrome/browser/ssl_client_certificate_selector.h"
16#include "chrome/browser/tab_contents/infobar_delegate.h"
17#include "chrome/browser/tab_contents/tab_contents.h"
18#include "chrome/common/notification_details.h"
19#include "chrome/common/notification_source.h"
20#include "grit/generated_resources.h"
21#include "grit/theme_resources.h"
22#include "net/base/net_errors.h"
23
24namespace {
25
26SkBitmap* GetCertIcon() {
27  // TODO(davidben): use a more appropriate icon.
28  return ResourceBundle::GetSharedInstance().GetBitmapNamed(
29      IDR_INFOBAR_SAVE_PASSWORD);
30}
31
32class SSLCertAddedInfoBarDelegate : public ConfirmInfoBarDelegate {
33 public:
34  SSLCertAddedInfoBarDelegate(TabContents* tab_contents,
35                              net::X509Certificate* cert)
36      : ConfirmInfoBarDelegate(tab_contents),
37        tab_contents_(tab_contents),
38        cert_(cert) {
39  }
40
41  virtual ~SSLCertAddedInfoBarDelegate() {
42  }
43
44  // Overridden from ConfirmInfoBarDelegate:
45  virtual string16 GetMessageText() const {
46    // TODO(evanm): GetDisplayName should return UTF-16.
47    return l10n_util::GetStringFUTF16(
48        IDS_ADD_CERT_SUCCESS_INFOBAR_LABEL,
49        UTF8ToUTF16(cert_->issuer().GetDisplayName()));
50  }
51
52  virtual SkBitmap* GetIcon() const {
53    return GetCertIcon();
54  }
55
56  virtual int GetButtons() const {
57    return BUTTON_OK;
58  }
59
60  virtual string16 GetButtonLabel(InfoBarButton button) const {
61    switch (button) {
62      case BUTTON_OK:
63        return l10n_util::GetStringUTF16(IDS_ADD_CERT_SUCCESS_INFOBAR_BUTTON);
64      default:
65        return string16();
66    }
67  }
68
69  virtual Type GetInfoBarType() {
70    return PAGE_ACTION_TYPE;
71  }
72
73  virtual bool Accept() {
74    ShowCertificateViewer(tab_contents_->GetMessageBoxRootWindow(), cert_);
75    return false;  // Hiding the infobar just as the dialog opens looks weird.
76  }
77
78  virtual void InfoBarClosed() {
79    // ConfirmInfoBarDelegate doesn't delete itself.
80    delete this;
81  }
82
83 private:
84  // The TabContents we are attached to
85  TabContents* tab_contents_;
86  // The cert we added.
87  scoped_refptr<net::X509Certificate> cert_;
88};
89
90}  // namespace
91
92class TabContentsSSLHelper::SSLAddCertData : public NotificationObserver {
93 public:
94  SSLAddCertData(TabContents* tab, SSLAddCertHandler* handler)
95      : tab_(tab),
96        handler_(handler),
97        infobar_delegate_(NULL) {
98    // Listen for disappearing InfoBars.
99    Source<TabContents> tc_source(tab_);
100    registrar_.Add(this, NotificationType::TAB_CONTENTS_INFOBAR_REMOVED,
101                   tc_source);
102    registrar_.Add(this, NotificationType::TAB_CONTENTS_INFOBAR_REPLACED,
103                   tc_source);
104  }
105  ~SSLAddCertData() {}
106
107  // Displays |delegate| as an infobar in |tab_|, replacing our current one if
108  // still active.
109  void ShowInfoBar(InfoBarDelegate* delegate) {
110    if (infobar_delegate_) {
111      tab_->ReplaceInfoBar(infobar_delegate_, delegate);
112    } else {
113      tab_->AddInfoBar(delegate);
114    }
115    infobar_delegate_ = delegate;
116  }
117
118  void ShowErrorInfoBar(const string16& message) {
119    ShowInfoBar(
120        new SimpleAlertInfoBarDelegate(tab_, message, GetCertIcon(), true));
121  }
122
123  // NotificationObserver implementation.
124  virtual void Observe(NotificationType type,
125                       const NotificationSource& source,
126                       const NotificationDetails& details) {
127    switch (type.value) {
128      case NotificationType::TAB_CONTENTS_INFOBAR_REMOVED:
129        InfoBarClosed(Details<InfoBarDelegate>(details).ptr());
130        break;
131      case NotificationType::TAB_CONTENTS_INFOBAR_REPLACED:
132        typedef std::pair<InfoBarDelegate*, InfoBarDelegate*>
133            InfoBarDelegatePair;
134        InfoBarClosed(Details<InfoBarDelegatePair>(details).ptr()->first);
135        break;
136      default:
137        NOTREACHED();
138        break;
139    }
140  }
141
142 private:
143  void InfoBarClosed(InfoBarDelegate* delegate) {
144    if (infobar_delegate_ == delegate)
145      infobar_delegate_ = NULL;
146  }
147
148  // The TabContents we are attached to.
149  TabContents* tab_;
150  // The handler we call back to.
151  scoped_refptr<SSLAddCertHandler> handler_;
152  // The current InfoBarDelegate we're displaying.
153  InfoBarDelegate* infobar_delegate_;
154
155  NotificationRegistrar registrar_;
156
157  DISALLOW_COPY_AND_ASSIGN(SSLAddCertData);
158};
159
160TabContentsSSLHelper::TabContentsSSLHelper(TabContents* tab_contents)
161    : tab_contents_(tab_contents) {
162}
163
164TabContentsSSLHelper::~TabContentsSSLHelper() {
165}
166
167void TabContentsSSLHelper::ShowClientCertificateRequestDialog(
168    scoped_refptr<SSLClientAuthHandler> handler) {
169  browser::ShowSSLClientCertificateSelector(
170      tab_contents_, handler->cert_request_info(), handler);
171}
172
173void TabContentsSSLHelper::OnVerifyClientCertificateError(
174    scoped_refptr<SSLAddCertHandler> handler, int error_code) {
175  SSLAddCertData* add_cert_data = GetAddCertData(handler);
176  // Display an infobar with the error message.
177  // TODO(davidben): Display a more user-friendly error string.
178  add_cert_data->ShowErrorInfoBar(
179      l10n_util::GetStringFUTF16(IDS_ADD_CERT_ERR_INVALID_CERT,
180                                 base::IntToString16(-error_code),
181                                 ASCIIToUTF16(net::ErrorToString(error_code))));
182}
183
184void TabContentsSSLHelper::AskToAddClientCertificate(
185    scoped_refptr<SSLAddCertHandler> handler) {
186  NOTREACHED();  // Not implemented yet.
187}
188
189void TabContentsSSLHelper::OnAddClientCertificateSuccess(
190    scoped_refptr<SSLAddCertHandler> handler) {
191  SSLAddCertData* add_cert_data = GetAddCertData(handler);
192  // Display an infobar to inform the user.
193  add_cert_data->ShowInfoBar(
194      new SSLCertAddedInfoBarDelegate(tab_contents_, handler->cert()));
195}
196
197void TabContentsSSLHelper::OnAddClientCertificateError(
198    scoped_refptr<SSLAddCertHandler> handler, int error_code) {
199  SSLAddCertData* add_cert_data = GetAddCertData(handler);
200  // Display an infobar with the error message.
201  // TODO(davidben): Display a more user-friendly error string.
202  add_cert_data->ShowErrorInfoBar(
203      l10n_util::GetStringFUTF16(IDS_ADD_CERT_ERR_FAILED,
204                                 base::IntToString16(-error_code),
205                                 ASCIIToUTF16(net::ErrorToString(error_code))));
206}
207
208void TabContentsSSLHelper::OnAddClientCertificateFinished(
209    scoped_refptr<SSLAddCertHandler> handler) {
210  // Clean up.
211  request_id_to_add_cert_data_.erase(handler->network_request_id());
212}
213
214TabContentsSSLHelper::SSLAddCertData* TabContentsSSLHelper::GetAddCertData(
215    SSLAddCertHandler* handler) {
216  // Find/create the slot.
217  linked_ptr<SSLAddCertData>& ptr_ref =
218      request_id_to_add_cert_data_[handler->network_request_id()];
219  // Fill it if necessary.
220  if (!ptr_ref.get())
221    ptr_ref.reset(new SSLAddCertData(tab_contents_, handler));
222  return ptr_ref.get();
223}
224