15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/certificate_dialogs.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
76e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)#include <algorithm>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/base64.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/bind.h"
121320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/files/file_util.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/ui/chrome_select_file_policy.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/net/x509_certificate_model.h"
171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "chrome/grit/generated_resources.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "content/public/browser/browser_thread.h"
19cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "net/base/filename_util.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/l10n/l10n_util.h"
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/shell_dialogs/select_file_dialog.h"
22cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "url/gurl.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::BrowserThread;
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using content::WebContents;
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void WriterCallback(const base::FilePath& path, const std::string& data) {
30a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)  int bytes_written = base::WriteFile(path, data.data(), data.size());
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (bytes_written != static_cast<ssize_t>(data.size())) {
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LOG(ERROR) << "Writing " << path.value() << " ("
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)               << data.size() << "B) returned " << bytes_written;
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void WriteFileOnFileThread(const base::FilePath& path,
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           const std::string& data) {
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  BrowserThread::PostTask(
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      BrowserThread::FILE, FROM_HERE, base::Bind(&WriterCallback, path, data));
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string WrapAt64(const std::string &str) {
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string result;
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < str.size(); i += 64) {
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result.append(str, i, 64);  // Append clamps the len arg internally.
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result.append("\r\n");
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string GetBase64String(net::X509Certificate::OSCertHandle cert) {
53116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  std::string der_cert;
54116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (!net::X509Certificate::GetDEREncoded(cert, &der_cert))
55116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    return std::string();
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string base64;
57116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  base::Base64Encode(der_cert, &base64);
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return "-----BEGIN CERTIFICATE-----\r\n" +
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      WrapAt64(base64) +
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      "-----END CERTIFICATE-----\r\n";
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)////////////////////////////////////////////////////////////////////////////////
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// General utility functions.
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class Exporter : public ui::SelectFileDialog::Listener {
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
686e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  Exporter(WebContents* web_contents,
696e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)           gfx::NativeWindow parent,
706e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)           net::X509Certificate::OSCertHandles::iterator certs_begin,
716e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)           net::X509Certificate::OSCertHandles::iterator certs_end);
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual ~Exporter();
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // SelectFileDialog::Listener implemenation.
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void FileSelected(const base::FilePath& path,
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                            int index, void* params) OVERRIDE;
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual void FileSelectionCanceled(void* params) OVERRIDE;
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_refptr<ui::SelectFileDialog> select_file_dialog_;
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The certificate hierarchy (leaf cert first).
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  net::X509Certificate::OSCertHandles cert_chain_list_;
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Exporter::Exporter(WebContents* web_contents,
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                   gfx::NativeWindow parent,
876e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                   net::X509Certificate::OSCertHandles::iterator certs_begin,
886e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                   net::X509Certificate::OSCertHandles::iterator certs_end)
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : select_file_dialog_(ui::SelectFileDialog::Create(
906e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)          this,
916e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)          new ChromeSelectFilePolicy(web_contents))) {
926e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  DCHECK(certs_begin != certs_end);
936e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  for (net::X509Certificate::OSCertHandles::iterator i = certs_begin;
946e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)       i != certs_end;
956e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)       ++i) {
966e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    cert_chain_list_.push_back(net::X509Certificate::DupOSCertHandle(*i));
976e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  }
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // TODO(mattm): should this default to some directory?
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Maybe SavePackage::GetSaveDirPreference? (Except that it's private.)
1016e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  std::string cert_title = x509_certificate_model::GetTitle(*certs_begin);
102cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  base::FilePath suggested_path =
103cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      net::GenerateFileName(GURL::EmptyGURL(),  // url
104cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                            std::string(),      // content_disposition
105cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                            std::string(),      // referrer_charset
106cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                            cert_title,         // suggested_name
107cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                            std::string(),      // mime_type
108cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                            "certificate");     // default_name
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ShowCertSelectFileDialog(select_file_dialog_.get(),
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           ui::SelectFileDialog::SELECT_SAVEAS_FILE,
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           suggested_path,
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           parent,
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                           NULL);
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Exporter::~Exporter() {
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // There may be pending file dialogs, we need to tell them that we've gone
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // away so they don't try and call back to us.
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (select_file_dialog_.get())
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    select_file_dialog_->ListenerDestroyed();
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1236e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  std::for_each(cert_chain_list_.begin(),
1246e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                cert_chain_list_.end(),
1256e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                &net::X509Certificate::FreeOSCertHandle);
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void Exporter::FileSelected(const base::FilePath& path, int index,
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                            void* params) {
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string data;
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (index) {
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case 2:
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      for (size_t i = 0; i < cert_chain_list_.size(); ++i)
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        data += GetBase64String(cert_chain_list_[i]);
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case 3:
137116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch      net::X509Certificate::GetDEREncoded(cert_chain_list_[0], &data);
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case 4:
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      data = x509_certificate_model::GetCMSString(cert_chain_list_, 0, 1);
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case 5:
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      data = x509_certificate_model::GetCMSString(
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          cert_chain_list_, 0, cert_chain_list_.size());
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case 1:
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    default:
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      data = GetBase64String(cert_chain_list_[0]);
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!data.empty())
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    WriteFileOnFileThread(path, data);
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delete this;
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Exporter::FileSelectionCanceled(void* params) {
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  delete this;
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ShowCertSelectFileDialog(ui::SelectFileDialog* select_file_dialog,
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              ui::SelectFileDialog::Type type,
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                              const base::FilePath& suggested_path,
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              gfx::NativeWindow parent,
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                              void* params) {
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ui::SelectFileDialog::FileTypeInfo file_type_info;
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  file_type_info.extensions.resize(5);
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  file_type_info.extensions[0].push_back(FILE_PATH_LITERAL("pem"));
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  file_type_info.extensions[0].push_back(FILE_PATH_LITERAL("crt"));
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  file_type_info.extension_description_overrides.push_back(
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      l10n_util::GetStringUTF16(IDS_CERT_EXPORT_TYPE_BASE64));
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  file_type_info.extensions[1].push_back(FILE_PATH_LITERAL("pem"));
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  file_type_info.extensions[1].push_back(FILE_PATH_LITERAL("crt"));
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  file_type_info.extension_description_overrides.push_back(
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      l10n_util::GetStringUTF16(IDS_CERT_EXPORT_TYPE_BASE64_CHAIN));
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  file_type_info.extensions[2].push_back(FILE_PATH_LITERAL("der"));
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  file_type_info.extension_description_overrides.push_back(
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      l10n_util::GetStringUTF16(IDS_CERT_EXPORT_TYPE_DER));
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  file_type_info.extensions[3].push_back(FILE_PATH_LITERAL("p7c"));
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  file_type_info.extension_description_overrides.push_back(
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      l10n_util::GetStringUTF16(IDS_CERT_EXPORT_TYPE_PKCS7));
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  file_type_info.extensions[4].push_back(FILE_PATH_LITERAL("p7c"));
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  file_type_info.extension_description_overrides.push_back(
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      l10n_util::GetStringUTF16(IDS_CERT_EXPORT_TYPE_PKCS7_CHAIN));
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  file_type_info.include_all_files = true;
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  select_file_dialog->SelectFile(
190a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      type, base::string16(),
1913240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      suggested_path, &file_type_info,
1923240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch      1,  // 1-based index for |file_type_info.extensions| to specify default.
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      FILE_PATH_LITERAL("crt"),
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      parent, params);
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ShowCertExportDialog(WebContents* web_contents,
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          gfx::NativeWindow parent,
1996e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)                          const scoped_refptr<net::X509Certificate>& cert) {
2006e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  net::X509Certificate::OSCertHandles cert_chain;
2016e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  cert_chain.push_back(cert->os_cert_handle());
2026e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  const net::X509Certificate::OSCertHandles& certs =
2036e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)      cert->GetIntermediateCertificates();
2046e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  cert_chain.insert(cert_chain.end(), certs.begin(), certs.end());
2056e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  new Exporter(web_contents, parent, cert_chain.begin(), cert_chain.end());
2066e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)}
2076e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)
2086e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)void ShowCertExportDialog(
2096e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    content::WebContents* web_contents,
2106e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    gfx::NativeWindow parent,
2116e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    net::X509Certificate::OSCertHandles::iterator certs_begin,
2126e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)    net::X509Certificate::OSCertHandles::iterator certs_end) {
2136e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles)  new Exporter(web_contents, parent, certs_begin, certs_end);
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
215