- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / webui / certificate_viewer_webui.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/ui/webui/certificate_viewer_webui.h"
6
7 #include "base/bind.h"
8 #include "base/bind_helpers.h"
9 #include "base/i18n/time_formatting.h"
10 #include "base/json/json_writer.h"
11 #include "base/strings/string_number_conversions.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "chrome/browser/certificate_viewer.h"
14 #include "chrome/browser/platform_util.h"
15 #include "chrome/browser/ui/browser_dialogs.h"
16 #include "chrome/browser/ui/certificate_dialogs.h"
17 #include "chrome/browser/ui/webui/constrained_web_dialog_ui.h"
18 #include "chrome/common/net/x509_certificate_model.h"
19 #include "chrome/common/url_constants.h"
20 #include "content/public/browser/web_contents.h"
21 #include "grit/generated_resources.h"
22 #include "ui/base/l10n/l10n_util.h"
23 #include "ui/gfx/size.h"
24
25 using content::WebContents;
26 using content::WebUIMessageHandler;
27 using web_modal::NativeWebContentsModalDialog;
28
29 // Shows a certificate using the WebUI certificate viewer.
30 void ShowCertificateViewer(WebContents* web_contents,
31                            gfx::NativeWindow parent,
32                            net::X509Certificate* cert) {
33   CertificateViewerDialog* dialog = new CertificateViewerDialog(cert);
34   dialog->Show(web_contents, parent);
35 }
36
37 ////////////////////////////////////////////////////////////////////////////////
38 // CertificateViewerDialog
39
40 CertificateViewerDialog::CertificateViewerDialog(net::X509Certificate* cert)
41     : cert_(cert), dialog_(NULL) {
42   // Construct the dialog title from the certificate.
43   net::X509Certificate::OSCertHandles cert_chain;
44   x509_certificate_model::GetCertChainFromCert(cert_->os_cert_handle(),
45       &cert_chain);
46   title_ = l10n_util::GetStringFUTF16(IDS_CERT_INFO_DIALOG_TITLE,
47       UTF8ToUTF16(x509_certificate_model::GetTitle(cert_chain.front())));
48 }
49
50 CertificateViewerDialog::~CertificateViewerDialog() {
51 }
52
53 void CertificateViewerDialog::Show(WebContents* web_contents,
54                                    gfx::NativeWindow parent) {
55   // TODO(bshe): UI tweaks needed for Aura HTML Dialog, such as adding padding
56   // on the title for Aura ConstrainedWebDialogUI.
57   dialog_ = CreateConstrainedWebDialog(
58       web_contents->GetBrowserContext(),
59       this,
60       NULL,
61       web_contents);
62 }
63
64 ui::ModalType CertificateViewerDialog::GetDialogModalType() const {
65   return ui::MODAL_TYPE_NONE;
66 }
67
68 string16 CertificateViewerDialog::GetDialogTitle() const {
69   return title_;
70 }
71
72 GURL CertificateViewerDialog::GetDialogContentURL() const {
73   return GURL(chrome::kChromeUICertificateViewerURL);
74 }
75
76 void CertificateViewerDialog::GetWebUIMessageHandlers(
77     std::vector<WebUIMessageHandler*>* handlers) const {
78   handlers->push_back(new CertificateViewerDialogHandler(
79       const_cast<CertificateViewerDialog*>(this), cert_.get()));
80 }
81
82 void CertificateViewerDialog::GetDialogSize(gfx::Size* size) const {
83   const int kDefaultWidth = 544;
84   const int kDefaultHeight = 628;
85   size->SetSize(kDefaultWidth, kDefaultHeight);
86 }
87
88 std::string CertificateViewerDialog::GetDialogArgs() const {
89   std::string data;
90
91   // Certificate information. The keys in this dictionary's general key
92   // correspond to the IDs in the Html page.
93   DictionaryValue cert_info;
94   net::X509Certificate::OSCertHandle cert_hnd = cert_->os_cert_handle();
95
96   // Get the certificate chain.
97   net::X509Certificate::OSCertHandles cert_chain;
98   x509_certificate_model::GetCertChainFromCert(cert_hnd, &cert_chain);
99
100   // Certificate usage.
101   std::vector<std::string> usages;
102   x509_certificate_model::GetUsageStrings(cert_hnd, &usages);
103   std::string usagestr;
104   for (std::vector<std::string>::iterator it = usages.begin();
105       it != usages.end(); ++it) {
106     if (usagestr.length() > 0) {
107       usagestr += "\n";
108     }
109     usagestr += *it;
110   }
111   cert_info.SetString("general.usages", usagestr);
112
113   // Standard certificate details.
114   const std::string alternative_text =
115       l10n_util::GetStringUTF8(IDS_CERT_INFO_FIELD_NOT_PRESENT);
116   cert_info.SetString("general.title", l10n_util::GetStringFUTF8(
117       IDS_CERT_INFO_DIALOG_TITLE, UTF8ToUTF16(x509_certificate_model::GetTitle(
118           cert_chain.front()))));
119
120   // Issued to information.
121   cert_info.SetString("general.issued-cn",
122       x509_certificate_model::GetSubjectCommonName(cert_hnd, alternative_text));
123   cert_info.SetString("general.issued-o",
124       x509_certificate_model::GetSubjectOrgName(cert_hnd, alternative_text));
125   cert_info.SetString("general.issued-ou",
126       x509_certificate_model::GetSubjectOrgUnitName(cert_hnd,
127                                                     alternative_text));
128   cert_info.SetString("general.issued-sn",
129       x509_certificate_model::GetSerialNumberHexified(cert_hnd,
130                                                       alternative_text));
131
132   // Issuer information.
133   cert_info.SetString("general.issuer-cn",
134       x509_certificate_model::GetIssuerCommonName(cert_hnd, alternative_text));
135   cert_info.SetString("general.issuer-o",
136       x509_certificate_model::GetIssuerOrgName(cert_hnd, alternative_text));
137   cert_info.SetString("general.issuer-ou",
138       x509_certificate_model::GetIssuerOrgUnitName(cert_hnd, alternative_text));
139
140   // Validity period.
141   base::Time issued, expires;
142   std::string issued_str, expires_str;
143   if (x509_certificate_model::GetTimes(cert_hnd, &issued, &expires)) {
144     issued_str = UTF16ToUTF8(
145         base::TimeFormatShortDateNumeric(issued));
146     expires_str = UTF16ToUTF8(
147         base::TimeFormatShortDateNumeric(expires));
148   } else {
149     issued_str = alternative_text;
150     expires_str = alternative_text;
151   }
152   cert_info.SetString("general.issue-date", issued_str);
153   cert_info.SetString("general.expiry-date", expires_str);
154
155   cert_info.SetString("general.sha256",
156       x509_certificate_model::HashCertSHA256(cert_hnd));
157   cert_info.SetString("general.sha1",
158       x509_certificate_model::HashCertSHA1(cert_hnd));
159
160   // Certificate hierarchy is constructed from bottom up.
161   ListValue* children = NULL;
162   int index = 0;
163   for (net::X509Certificate::OSCertHandles::const_iterator i =
164       cert_chain.begin(); i != cert_chain.end(); ++i, ++index) {
165     DictionaryValue* cert_node = new DictionaryValue();
166     ListValue cert_details;
167     cert_node->SetString("label", x509_certificate_model::GetTitle(*i).c_str());
168     cert_node->SetDouble("payload.index", index);
169     // Add the child from the previous iteration.
170     if (children)
171       cert_node->Set("children", children);
172
173     // Add this node to the children list for the next iteration.
174     children = new ListValue();
175     children->Append(cert_node);
176   }
177   // Set the last node as the top of the certificate hierarchy.
178   cert_info.Set("hierarchy", children);
179
180   base::JSONWriter::Write(&cert_info, &data);
181
182   return data;
183 }
184
185 void CertificateViewerDialog::OnDialogShown(
186     content::WebUI* webui,
187     content::RenderViewHost* render_view_host) {
188 }
189
190 void CertificateViewerDialog::OnDialogClosed(const std::string& json_retval) {
191 }
192
193 void CertificateViewerDialog::OnCloseContents(WebContents* source,
194                                               bool* out_close_dialog) {
195   if (out_close_dialog)
196     *out_close_dialog = true;
197 }
198
199 bool CertificateViewerDialog::ShouldShowDialogTitle() const {
200   return true;
201 }
202
203 ////////////////////////////////////////////////////////////////////////////////
204 // CertificateViewerDialogHandler
205
206 CertificateViewerDialogHandler::CertificateViewerDialogHandler(
207     CertificateViewerDialog* dialog,
208     net::X509Certificate* cert) : cert_(cert), dialog_(dialog) {
209   x509_certificate_model::GetCertChainFromCert(cert_->os_cert_handle(),
210       &cert_chain_);
211 }
212
213 CertificateViewerDialogHandler::~CertificateViewerDialogHandler() {
214 }
215
216 void CertificateViewerDialogHandler::RegisterMessages() {
217   web_ui()->RegisterMessageCallback("exportCertificate",
218       base::Bind(&CertificateViewerDialogHandler::ExportCertificate,
219                  base::Unretained(this)));
220   web_ui()->RegisterMessageCallback("requestCertificateFields",
221       base::Bind(&CertificateViewerDialogHandler::RequestCertificateFields,
222                  base::Unretained(this)));
223 }
224
225 void CertificateViewerDialogHandler::ExportCertificate(
226     const base::ListValue* args) {
227   int cert_index = GetCertificateIndex(args);
228   if (cert_index < 0)
229     return;
230
231   NativeWebContentsModalDialog window =
232       platform_util::GetTopLevel(dialog_->dialog()->GetNativeDialog());
233   ShowCertExportDialog(web_ui()->GetWebContents(),
234                        window,
235                        cert_chain_[cert_index]);
236 }
237
238 void CertificateViewerDialogHandler::RequestCertificateFields(
239     const base::ListValue* args) {
240   int cert_index = GetCertificateIndex(args);
241   if (cert_index < 0)
242     return;
243
244   net::X509Certificate::OSCertHandle cert = cert_chain_[cert_index];
245
246   ListValue root_list;
247   DictionaryValue* node_details;
248   DictionaryValue* alt_node_details;
249   ListValue* cert_sub_fields;
250   root_list.Append(node_details = new DictionaryValue());
251   node_details->SetString("label", x509_certificate_model::GetTitle(cert));
252
253   ListValue* cert_fields;
254   node_details->Set("children", cert_fields = new ListValue());
255   cert_fields->Append(node_details = new DictionaryValue());
256
257   node_details->SetString("label",
258       l10n_util::GetStringUTF8(IDS_CERT_DETAILS_CERTIFICATE));
259   node_details->Set("children", cert_fields = new ListValue());
260
261   // Main certificate fields.
262   cert_fields->Append(node_details = new DictionaryValue());
263   node_details->SetString("label",
264       l10n_util::GetStringUTF8(IDS_CERT_DETAILS_VERSION));
265   std::string version = x509_certificate_model::GetVersion(cert);
266   if (!version.empty())
267     node_details->SetString("payload.val",
268         l10n_util::GetStringFUTF8(IDS_CERT_DETAILS_VERSION_FORMAT,
269                                   UTF8ToUTF16(version)));
270
271   cert_fields->Append(node_details = new DictionaryValue());
272   node_details->SetString("label",
273       l10n_util::GetStringUTF8(IDS_CERT_DETAILS_SERIAL_NUMBER));
274   node_details->SetString("payload.val",
275       x509_certificate_model::GetSerialNumberHexified(cert,
276           l10n_util::GetStringUTF8(IDS_CERT_INFO_FIELD_NOT_PRESENT)));
277
278   cert_fields->Append(node_details = new DictionaryValue());
279   node_details->SetString("label",
280       l10n_util::GetStringUTF8(IDS_CERT_DETAILS_CERTIFICATE_SIG_ALG));
281   node_details->SetString("payload.val",
282       x509_certificate_model::ProcessSecAlgorithmSignature(cert));
283
284   cert_fields->Append(node_details = new DictionaryValue());
285   node_details->SetString("label",
286       l10n_util::GetStringUTF8(IDS_CERT_DETAILS_ISSUER));
287   node_details->SetString("payload.val",
288       x509_certificate_model::GetIssuerName(cert));
289
290   // Validity period.
291   cert_fields->Append(node_details = new DictionaryValue());
292   node_details->SetString("label",
293       l10n_util::GetStringUTF8(IDS_CERT_DETAILS_VALIDITY));
294
295   node_details->Set("children", cert_sub_fields = new ListValue());
296   cert_sub_fields->Append(node_details = new DictionaryValue());
297   node_details->SetString("label",
298       l10n_util::GetStringUTF8(IDS_CERT_DETAILS_NOT_BEFORE));
299   cert_sub_fields->Append(alt_node_details = new DictionaryValue());
300   alt_node_details->SetString("label",
301       l10n_util::GetStringUTF8(IDS_CERT_DETAILS_NOT_AFTER));
302   base::Time issued, expires;
303   if (x509_certificate_model::GetTimes(cert, &issued, &expires)) {
304     node_details->SetString("payload.val",
305         UTF16ToUTF8(base::TimeFormatShortDateAndTime(issued)));
306     alt_node_details->SetString("payload.val",
307         UTF16ToUTF8(base::TimeFormatShortDateAndTime(expires)));
308   }
309
310   cert_fields->Append(node_details = new DictionaryValue());
311   node_details->SetString("label",
312       l10n_util::GetStringUTF8(IDS_CERT_DETAILS_SUBJECT));
313   node_details->SetString("payload.val",
314       x509_certificate_model::GetSubjectName(cert));
315
316   // Subject key information.
317   cert_fields->Append(node_details = new DictionaryValue());
318   node_details->SetString("label",
319       l10n_util::GetStringUTF8(IDS_CERT_DETAILS_SUBJECT_KEY_INFO));
320
321   node_details->Set("children", cert_sub_fields = new ListValue());
322   cert_sub_fields->Append(node_details = new DictionaryValue());
323   node_details->SetString("label",
324       l10n_util::GetStringUTF8(IDS_CERT_DETAILS_SUBJECT_KEY_ALG));
325   node_details->SetString("payload.val",
326       x509_certificate_model::ProcessSecAlgorithmSubjectPublicKey(cert));
327   cert_sub_fields->Append(node_details = new DictionaryValue());
328   node_details->SetString("label",
329       l10n_util::GetStringUTF8(IDS_CERT_DETAILS_SUBJECT_KEY));
330   node_details->SetString("payload.val",
331       x509_certificate_model::ProcessSubjectPublicKeyInfo(cert));
332
333   // Extensions.
334   x509_certificate_model::Extensions extensions;
335   x509_certificate_model::GetExtensions(
336       l10n_util::GetStringUTF8(IDS_CERT_EXTENSION_CRITICAL),
337       l10n_util::GetStringUTF8(IDS_CERT_EXTENSION_NON_CRITICAL),
338       cert, &extensions);
339
340   if (!extensions.empty()) {
341     cert_fields->Append(node_details = new DictionaryValue());
342     node_details->SetString("label",
343         l10n_util::GetStringUTF8(IDS_CERT_DETAILS_EXTENSIONS));
344
345     node_details->Set("children", cert_sub_fields = new ListValue());
346     for (x509_certificate_model::Extensions::const_iterator i =
347          extensions.begin(); i != extensions.end(); ++i) {
348       cert_sub_fields->Append(node_details = new DictionaryValue());
349       node_details->SetString("label", i->name);
350       node_details->SetString("payload.val", i->value);
351     }
352   }
353
354   cert_fields->Append(node_details = new DictionaryValue());
355   node_details->SetString("label",
356       l10n_util::GetStringUTF8(IDS_CERT_DETAILS_CERTIFICATE_SIG_ALG));
357   node_details->SetString("payload.val",
358       x509_certificate_model::ProcessSecAlgorithmSignatureWrap(cert));
359
360   cert_fields->Append(node_details = new DictionaryValue());
361   node_details->SetString("label",
362       l10n_util::GetStringUTF8(IDS_CERT_DETAILS_CERTIFICATE_SIG_VALUE));
363   node_details->SetString("payload.val",
364       x509_certificate_model::ProcessRawBitsSignatureWrap(cert));
365
366   cert_fields->Append(node_details = new DictionaryValue());
367   node_details->SetString("label",
368       l10n_util::GetStringUTF8(IDS_CERT_INFO_FINGERPRINTS_GROUP));
369   node_details->Set("children", cert_sub_fields = new ListValue());
370
371   cert_sub_fields->Append(node_details = new DictionaryValue());
372   node_details->SetString("label",
373       l10n_util::GetStringUTF8(IDS_CERT_INFO_SHA256_FINGERPRINT_LABEL));
374   node_details->SetString("payload.val",
375       x509_certificate_model::HashCertSHA256(cert));
376   cert_sub_fields->Append(node_details = new DictionaryValue());
377   node_details->SetString("label",
378       l10n_util::GetStringUTF8(IDS_CERT_INFO_SHA1_FINGERPRINT_LABEL));
379   node_details->SetString("payload.val",
380       x509_certificate_model::HashCertSHA1(cert));
381
382   // Send certificate information to javascript.
383   web_ui()->CallJavascriptFunction("cert_viewer.getCertificateFields",
384       root_list);
385 }
386
387 int CertificateViewerDialogHandler::GetCertificateIndex(
388     const base::ListValue* args) const {
389   int cert_index;
390   double val;
391   if (!(args->GetDouble(0, &val)))
392     return -1;
393   cert_index = static_cast<int>(val);
394   if (cert_index < 0 || cert_index >= static_cast<int>(cert_chain_.size()))
395     return -1;
396   return cert_index;
397 }