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