Upstream version 11.40.277.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / ssl / ssl_add_certificate.cc
1 // Copyright (c) 2012 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/ssl_add_certificate.h"
6
7 #include "base/basictypes.h"
8 #include "base/strings/string_number_conversions.h"
9 #include "base/strings/utf_string_conversions.h"
10 #include "chrome/browser/certificate_viewer.h"
11 #include "chrome/browser/infobars/infobar_service.h"
12 #include "chrome/browser/infobars/simple_alert_infobar_delegate.h"
13 #include "chrome/grit/generated_resources.h"
14 #include "components/infobars/core/confirm_infobar_delegate.h"
15 #include "components/infobars/core/infobar.h"
16 #include "content/public/browser/browser_thread.h"
17 #include "content/public/browser/render_frame_host.h"
18 #include "content/public/browser/web_contents.h"
19 #include "grit/theme_resources.h"
20 #include "net/base/net_errors.h"
21 #include "net/cert/cert_database.h"
22 #include "net/cert/x509_certificate.h"
23 #include "ui/base/l10n/l10n_util.h"
24
25 using content::BrowserThread;
26 using content::RenderFrameHost;
27 using content::WebContents;
28
29 namespace chrome {
30
31 namespace {
32
33 class SSLAddCertificateInfoBarDelegate : public ConfirmInfoBarDelegate {
34  public:
35   // Creates an SSL certificate enrollment result infobar and delegate.
36   static void Create(InfoBarService* infobar_service,
37                      net::X509Certificate* cert) {
38     infobar_service->AddInfoBar(ConfirmInfoBarDelegate::CreateInfoBar(
39         scoped_ptr<ConfirmInfoBarDelegate>(
40             new SSLAddCertificateInfoBarDelegate(cert))));
41   }
42
43  private:
44   explicit SSLAddCertificateInfoBarDelegate(net::X509Certificate* cert)
45       : cert_(cert) {}
46   ~SSLAddCertificateInfoBarDelegate() override {}
47
48   // ConfirmInfoBarDelegate implementation:
49   int GetIconID() const override {
50     // TODO(davidben): Use a more appropriate icon.
51     return IDR_INFOBAR_SAVE_PASSWORD;
52   }
53
54   Type GetInfoBarType() const override { return PAGE_ACTION_TYPE; }
55
56   base::string16 GetMessageText() const override {
57     // TODO(evanm): GetDisplayName should return UTF-16.
58     return l10n_util::GetStringFUTF16(IDS_ADD_CERT_SUCCESS_INFOBAR_LABEL,
59                                       base::UTF8ToUTF16(
60                                           cert_->issuer().GetDisplayName()));
61   }
62
63   int GetButtons() const override { return BUTTON_OK; }
64
65   base::string16 GetButtonLabel(InfoBarButton button) const override {
66     DCHECK_EQ(BUTTON_OK, button);
67     return l10n_util::GetStringUTF16(IDS_ADD_CERT_SUCCESS_INFOBAR_BUTTON);
68   }
69
70   bool Accept() override {
71     WebContents* web_contents =
72         InfoBarService::WebContentsFromInfoBar(infobar());
73     ShowCertificateViewer(web_contents,
74                           web_contents->GetTopLevelNativeWindow(),
75                           cert_.get());
76     // It looks weird to hide the infobar just as the dialog opens.
77     return false;
78   }
79
80   // The certificate that was added.
81   scoped_refptr<net::X509Certificate> cert_;
82
83   DISALLOW_COPY_AND_ASSIGN(SSLAddCertificateInfoBarDelegate);
84 };
85
86 void ShowErrorInfoBar(int message_id,
87                       int render_process_id,
88                       int render_frame_id,
89                       int cert_error) {
90   WebContents* web_contents = WebContents::FromRenderFrameHost(
91       RenderFrameHost::FromID(render_process_id, render_frame_id));
92   if (!web_contents)
93     return;
94
95   // TODO(davidben): Use a more appropriate icon.
96   // TODO(davidben): Display a more user-friendly error string.
97   SimpleAlertInfoBarDelegate::Create(
98       InfoBarService::FromWebContents(web_contents),
99       IDR_INFOBAR_SAVE_PASSWORD,
100       l10n_util::GetStringFUTF16(IDS_ADD_CERT_ERR_INVALID_CERT,
101                                  base::IntToString16(-cert_error),
102                                  base::ASCIIToUTF16(
103                                      net::ErrorToString(cert_error))),
104       true);
105 }
106
107 void ShowSuccessInfoBar(int render_process_id,
108                         int render_frame_id,
109                         net::X509Certificate* cert) {
110   WebContents* web_contents = WebContents::FromRenderFrameHost(
111       RenderFrameHost::FromID(render_process_id, render_frame_id));
112   if (!web_contents)
113     return;
114
115   SSLAddCertificateInfoBarDelegate::Create(
116       InfoBarService::FromWebContents(web_contents), cert);
117 }
118
119 }  // namespace
120
121 void SSLAddCertificate(
122     net::CertificateMimeType cert_type,
123     const void* cert_data,
124     size_t cert_size,
125     int render_process_id,
126     int render_frame_id) {
127   // Chromium only supports X.509 User certificates on non-Android
128   // platforms. Note that this method should not be called for other
129   // certificate mime types.
130   if (cert_type != net::CERTIFICATE_MIME_TYPE_X509_USER_CERT)
131     return;
132
133   scoped_refptr<net::X509Certificate> cert;
134   if (cert_data != NULL) {
135     cert = net::X509Certificate::CreateFromBytes(
136         reinterpret_cast<const char*>(cert_data), cert_size);
137   }
138   // NOTE: Passing a NULL cert pointer if |cert_data| was NULL is
139   // intentional here.
140
141   // Check if we have a corresponding private key.
142   int cert_error = net::CertDatabase::GetInstance()->CheckUserCert(cert.get());
143   if (cert_error != net::OK) {
144     LOG_IF(ERROR, cert_error == net::ERR_NO_PRIVATE_KEY_FOR_CERT)
145         << "No corresponding private key in store for cert: "
146         << (cert.get() ? cert->subject().GetDisplayName() : "NULL");
147
148     BrowserThread::PostTask(
149       BrowserThread::UI, FROM_HERE,
150       base::Bind(&ShowErrorInfoBar, IDS_ADD_CERT_ERR_INVALID_CERT,
151                  render_process_id, render_frame_id, cert_error));
152     return;
153   }
154
155   // Install it.
156   cert_error = net::CertDatabase::GetInstance()->AddUserCert(cert.get());
157
158   // Show the appropriate infobar.
159   if (cert_error != net::OK) {
160     BrowserThread::PostTask(
161       BrowserThread::UI, FROM_HERE,
162       base::Bind(&ShowErrorInfoBar, IDS_ADD_CERT_ERR_FAILED,
163                  render_process_id, render_frame_id, cert_error));
164   } else {
165     BrowserThread::PostTask(
166         BrowserThread::UI, FROM_HERE,
167         base::Bind(&ShowSuccessInfoBar,
168                    render_process_id, render_frame_id, cert));
169   }
170 }
171
172 }  // namespace chrome