summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authormattm@chromium.org <mattm@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-09-29 21:59:17 +0000
committermattm@chromium.org <mattm@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-09-29 21:59:17 +0000
commit0fd776c40893cb7c9e02c0060a818a7fe972f1aa (patch)
tree601700d589a09e12faf4c959d8b2b40bfd3b6432
parent808ae47cffd55a3d761151eb4da93a5befefd922 (diff)
downloadchromium_src-0fd776c40893cb7c9e02c0060a818a7fe972f1aa.zip
chromium_src-0fd776c40893cb7c9e02c0060a818a7fe972f1aa.tar.gz
chromium_src-0fd776c40893cb7c9e02c0060a818a7fe972f1aa.tar.bz2
DOMUI options: NSS Certificate manager part 1 (read only)
BUG=19991 TEST=run with --enable-tabbed-options, click certificate manager button in options Review URL: http://codereview.chromium.org/3389001 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@60996 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--app/l10n_util_collator.h3
-rw-r--r--chrome/app/generated_resources.grd6
-rw-r--r--chrome/browser/certificate_manager_model.cc111
-rw-r--r--chrome/browser/certificate_manager_model.h54
-rw-r--r--chrome/browser/dom_ui/advanced_options_handler.cc6
-rw-r--r--chrome/browser/dom_ui/advanced_options_handler.h2
-rw-r--r--chrome/browser/dom_ui/advanced_options_utils_gtk.cc11
-rw-r--r--chrome/browser/dom_ui/certificate_manager_handler.cc225
-rw-r--r--chrome/browser/dom_ui/certificate_manager_handler.h40
-rw-r--r--chrome/browser/dom_ui/options_ui.cc7
-rw-r--r--chrome/browser/resources/options.html17
-rw-r--r--chrome/browser/resources/options/advanced_options.html4
-rw-r--r--chrome/browser/resources/options/advanced_options.js15
-rw-r--r--chrome/browser/resources/options/certificate_manager.css15
-rw-r--r--chrome/browser/resources/options/certificate_manager.html106
-rw-r--r--chrome/browser/resources/options/certificate_manager.js117
-rw-r--r--chrome/browser/resources/options/certificate_tree.js120
-rw-r--r--chrome/chrome_browser.gypi9
18 files changed, 847 insertions, 21 deletions
diff --git a/app/l10n_util_collator.h b/app/l10n_util_collator.h
index 98011d9..d5b3f81 100644
--- a/app/l10n_util_collator.h
+++ b/app/l10n_util_collator.h
@@ -20,6 +20,9 @@ namespace l10n_util {
UCollationResult CompareStringWithCollator(const icu::Collator* collator,
const std::wstring& lhs,
const std::wstring& rhs);
+UCollationResult CompareString16WithCollator(const icu::Collator* collator,
+ const string16& lhs,
+ const string16& rhs);
// Used by SortStringsUsingMethod. Invokes a method on the objects passed to
// operator (), comparing the string results using a collator.
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index b5748b0..75be640 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -3139,8 +3139,8 @@ each locale. -->
<message name="IDS_CERT_MANAGER_NAME_COLUMN_LABEL" desc="Label for the certificate name column of the certificate tree in the certificate manager">
Certificate Name
</message>
- <message name="IDS_CERT_MANAGER_DEVICE_COLUMN_LABEL" desc="Label for the security device column of the certificate tree in the certificate manager">
- Security Device
+ <message name="IDS_CERT_MANAGER_DEVICE_COLUMN_LABEL" desc="Label for the certificate store column of the certificate tree in the certificate manager">
+ Certificate Store
</message>
<message name="IDS_CERT_MANAGER_SERIAL_NUMBER_COLUMN_LABEL" desc="Label for the serial number column of the certificate tree in the certificate manager">
Serial Number
@@ -3152,7 +3152,7 @@ each locale. -->
Email Address
</message>
<message name="IDS_CERT_MANAGER_VIEW_CERT_BUTTON" desc="Label for the button in the certificate manager which launches the certificate viewer for the selected certificate">
- &amp;View
+ View
</message>
<!-- Add Client Certificate Dialog -->
diff --git a/chrome/browser/certificate_manager_model.cc b/chrome/browser/certificate_manager_model.cc
new file mode 100644
index 0000000..170bc7a
--- /dev/null
+++ b/chrome/browser/certificate_manager_model.cc
@@ -0,0 +1,111 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/certificate_manager_model.h"
+
+#include <cert.h>
+
+#include "base/i18n/time_formatting.h"
+#include "base/logging.h"
+#include "base/utf_string_conversions.h"
+#include "chrome/third_party/mozilla_security_manager/nsNSSCertHelper.h"
+#include "chrome/third_party/mozilla_security_manager/nsNSSCertificate.h"
+#include "net/base/x509_certificate.h"
+
+// TODO(mattm): Try to make this use only X509Certificate stuff rather than NSS
+// functions in some places. (Not very important at this time since this is only
+// used w/NSS anyway.)
+
+// PSM = Mozilla's Personal Security Manager.
+namespace psm = mozilla_security_manager;
+
+namespace {
+
+// Convert a char* return value from NSS into a std::string and free the NSS
+// memory. If the arg is NULL, an empty string will be returned instead.
+std::string Stringize(char* nss_text) {
+ std::string s;
+ if (nss_text) {
+ s = nss_text;
+ PORT_Free(nss_text);
+ }
+ return s;
+}
+
+std::string GetCertNameOrNickname(CERTCertificate* os_cert) {
+ std::string name = psm::ProcessIDN(
+ Stringize(CERT_GetCommonName(&os_cert->subject)));
+ if (name.empty() && os_cert->nickname) {
+ name = os_cert->nickname;
+ // Hack copied from mozilla: Cut off text before first :, which seems to
+ // just be the token name.
+ size_t colon_pos = name.find(':');
+ if (colon_pos != std::string::npos)
+ name = name.substr(colon_pos + 1);
+ }
+ return name;
+}
+
+} // namespace
+
+CertificateManagerModel::CertificateManagerModel() {
+}
+
+CertificateManagerModel::~CertificateManagerModel() {
+}
+
+void CertificateManagerModel::Refresh() {
+ cert_db_.ListCerts(&cert_list_);
+}
+
+void CertificateManagerModel::FilterAndBuildOrgGroupingMap(
+ net::CertType filter_type,
+ CertificateManagerModel::OrgGroupingMap* map) const {
+ for (net::CertificateList::const_iterator i = cert_list_.begin();
+ i != cert_list_.end(); ++i) {
+ net::X509Certificate* cert = i->get();
+ net::CertType type = psm::GetCertType(cert->os_cert_handle());
+ if (type != filter_type)
+ continue;
+
+ std::string org;
+ if (!cert->subject().organization_names.empty())
+ org = cert->subject().organization_names[0];
+ if (org.empty())
+ org = cert->subject().GetDisplayName();
+
+ (*map)[org].push_back(cert);
+ }
+}
+
+string16 CertificateManagerModel::GetColumnText(
+ const net::X509Certificate& cert,
+ Column column) const {
+ string16 rv;
+ switch (column) {
+ case COL_SUBJECT_NAME:
+ rv = UTF8ToUTF16(GetCertNameOrNickname(cert.os_cert_handle()));
+ break;
+ case COL_CERTIFICATE_STORE:
+ rv = UTF8ToUTF16(psm::GetCertTokenName(cert.os_cert_handle()));
+ break;
+ case COL_SERIAL_NUMBER:
+ rv = ASCIIToUTF16(Stringize(CERT_Hexify(
+ &cert.os_cert_handle()->serialNumber, PR_TRUE)));
+ break;
+ case COL_EXPIRES_ON:
+ if (!cert.valid_expiry().is_null()) {
+ rv = WideToUTF16Hack(
+ base::TimeFormatShortDateNumeric(cert.valid_expiry()));
+ }
+ break;
+ case COL_EMAIL_ADDRESS:
+ if (cert.os_cert_handle()->emailAddr)
+ rv = UTF8ToUTF16(cert.os_cert_handle()->emailAddr);
+ break;
+ default:
+ NOTREACHED();
+ }
+ return rv;
+}
diff --git a/chrome/browser/certificate_manager_model.h b/chrome/browser/certificate_manager_model.h
new file mode 100644
index 0000000..ce45d3a
--- /dev/null
+++ b/chrome/browser/certificate_manager_model.h
@@ -0,0 +1,54 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_CERTIFICATE_MANAGER_MODEL_H_
+#define CHROME_BROWSER_CERTIFICATE_MANAGER_MODEL_H_
+
+#include <map>
+#include <string>
+
+#include "base/ref_counted.h"
+#include "base/string16.h"
+#include "net/base/cert_database.h"
+
+// CertificateManagerModel provides the data to be displayed in the certificate
+// manager dialog, and processes changes from the view.
+class CertificateManagerModel {
+ public:
+ // Map from the subject organization name to the list of certs from that
+ // organization. If a cert does not have an organization name, the
+ // subject's CertPrincipal::GetDisplayName() value is used instead.
+ typedef std::map<std::string, net::CertificateList> OrgGroupingMap;
+
+ // Enumeration of the possible columns in the certificate manager tree view.
+ enum Column {
+ COL_SUBJECT_NAME,
+ COL_CERTIFICATE_STORE,
+ COL_SERIAL_NUMBER,
+ COL_EXPIRES_ON,
+ COL_EMAIL_ADDRESS,
+ };
+
+ CertificateManagerModel();
+ ~CertificateManagerModel();
+
+ // Refresh the list of certs. Following this call, the view should call
+ // FilterAndBuildOrgGroupingMap as necessary to refresh its tree views.
+ void Refresh();
+
+ // Fill |map| with the certificates matching |filter_type|.
+ void FilterAndBuildOrgGroupingMap(net::CertType filter_type,
+ OrgGroupingMap* map) const;
+
+ // Get the data to be displayed in |column| for the given |cert|.
+ string16 GetColumnText(const net::X509Certificate& cert, Column column) const;
+
+ private:
+ net::CertDatabase cert_db_;
+ net::CertificateList cert_list_;
+
+ DISALLOW_COPY_AND_ASSIGN(CertificateManagerModel);
+};
+
+#endif // CHROME_BROWSER_CERTIFICATE_MANAGER_MODEL_H_
diff --git a/chrome/browser/dom_ui/advanced_options_handler.cc b/chrome/browser/dom_ui/advanced_options_handler.cc
index b64f736..778dab6 100644
--- a/chrome/browser/dom_ui/advanced_options_handler.cc
+++ b/chrome/browser/dom_ui/advanced_options_handler.cc
@@ -205,10 +205,12 @@ void AdvancedOptionsHandler::RegisterMessages() {
dom_ui_->RegisterMessageCallback("metricsReportingCheckboxAction",
NewCallback(this,
&AdvancedOptionsHandler::HandleMetricsReportingCheckbox));
-#if !defined(OS_CHROMEOS)
+#if !defined(USE_NSS)
dom_ui_->RegisterMessageCallback("showManageSSLCertificates",
NewCallback(this,
&AdvancedOptionsHandler::ShowManageSSLCertificates));
+#endif
+#if !defined(OS_CHROMEOS)
dom_ui_->RegisterMessageCallback("showNetworkProxySettings",
NewCallback(this,
&AdvancedOptionsHandler::ShowNetworkProxySettings));
@@ -322,7 +324,9 @@ void AdvancedOptionsHandler::ShowNetworkProxySettings(const ListValue* args) {
UserMetricsRecordAction(UserMetricsAction("Options_ShowProxySettings"));
AdvancedOptionsUtilities::ShowNetworkProxySettings(dom_ui_->tab_contents());
}
+#endif
+#if !defined(USE_NSS)
void AdvancedOptionsHandler::ShowManageSSLCertificates(const ListValue* args) {
UserMetricsRecordAction(UserMetricsAction("Options_ManageSSLCertificates"));
AdvancedOptionsUtilities::ShowManageSSLCertificates(dom_ui_->tab_contents());
diff --git a/chrome/browser/dom_ui/advanced_options_handler.h b/chrome/browser/dom_ui/advanced_options_handler.h
index 2896d97..f85ec2a 100644
--- a/chrome/browser/dom_ui/advanced_options_handler.h
+++ b/chrome/browser/dom_ui/advanced_options_handler.h
@@ -70,7 +70,9 @@ class AdvancedOptionsHandler
// Callback for the "showNetworkProxySettings" message. This will invoke
// an appropriate dialog for configuring proxy settings.
void ShowNetworkProxySettings(const ListValue* args);
+#endif
+#if !defined(USE_NSS)
// Callback for the "showManageSSLCertificates" message. This will invoke
// an appropriate certificate management action based on the platform.
void ShowManageSSLCertificates(const ListValue* args);
diff --git a/chrome/browser/dom_ui/advanced_options_utils_gtk.cc b/chrome/browser/dom_ui/advanced_options_utils_gtk.cc
index 7226f61..b471616 100644
--- a/chrome/browser/dom_ui/advanced_options_utils_gtk.cc
+++ b/chrome/browser/dom_ui/advanced_options_utils_gtk.cc
@@ -29,11 +29,6 @@ const char* kKDE4ProxyConfigCommand[] = {"kcmshell4", "proxy", NULL};
// supported desktop environment.
const char kLinuxProxyConfigUrl[] = "about:linux-proxy-config";
-// The URL for Linux ssl certificate configuration help.
-const char* const kLinuxCertificatesConfigUrl =
- "http://code.google.com/p/chromium/wiki/LinuxCertManagement";
-
-
struct ProxyConfigCommand {
std::string binary;
const char** argv;
@@ -123,10 +118,4 @@ void AdvancedOptionsUtilities::ShowNetworkProxySettings(
}
}
-void AdvancedOptionsUtilities::ShowManageSSLCertificates(
- TabContents* tab_contents) {
- tab_contents->OpenURL(GURL(kLinuxCertificatesConfigUrl), GURL(),
- NEW_FOREGROUND_TAB, PageTransition::LINK);
-}
-
#endif // !defined(OS_CHROMEOS)
diff --git a/chrome/browser/dom_ui/certificate_manager_handler.cc b/chrome/browser/dom_ui/certificate_manager_handler.cc
new file mode 100644
index 0000000..08d5641
--- /dev/null
+++ b/chrome/browser/dom_ui/certificate_manager_handler.cc
@@ -0,0 +1,225 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/dom_ui/certificate_manager_handler.h"
+
+#include "app/l10n_util.h"
+#include "app/l10n_util_collator.h"
+#include "base/string_number_conversions.h"
+#include "base/values.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/certificate_manager_model.h"
+#include "chrome/browser/certificate_viewer.h"
+#include "chrome/browser/tab_contents/tab_contents.h"
+#include "chrome/browser/tab_contents/tab_contents_view.h"
+#include "grit/generated_resources.h"
+#include "net/base/x509_certificate.h"
+
+namespace {
+
+static const char kKeyId[] = "id";
+static const char kSubNodesId[] = "subnodes";
+static const char kNameId[] = "name";
+static const char kIconId[] = "icon";
+static const char kSecurityDeviceId[] = "device";
+
+// TODO(mattm): These are duplicated from cookies_view_handler.cc
+// Encodes a pointer value into a hex string.
+std::string PointerToHexString(const void* pointer) {
+ return base::HexEncode(&pointer, sizeof(pointer));
+}
+
+// Decodes a pointer from a hex string.
+void* HexStringToPointer(const std::string& str) {
+ std::vector<uint8> buffer;
+ if (!base::HexStringToBytes(str, &buffer) ||
+ buffer.size() != sizeof(void*)) {
+ return NULL;
+ }
+
+ return *reinterpret_cast<void**>(&buffer[0]);
+}
+
+std::string OrgNameToId(const std::string& org) {
+ return "org-" + org;
+}
+
+std::string CertToId(const net::X509Certificate& cert) {
+ return "cert-" + PointerToHexString(&cert);
+}
+
+net::X509Certificate* IdToCert(const std::string& id) {
+ if (!StartsWithASCII(id, "cert-", true))
+ return NULL;
+ return reinterpret_cast<net::X509Certificate*>(HexStringToPointer(id.substr(5)));
+}
+
+struct DictionaryIdComparator {
+ DictionaryIdComparator(icu::Collator* collator) : collator_(collator) {
+ }
+
+ bool operator()(const Value* a,
+ const Value* b) const {
+ DCHECK(a->GetType() == Value::TYPE_DICTIONARY);
+ DCHECK(b->GetType() == Value::TYPE_DICTIONARY);
+ const DictionaryValue* a_dict = reinterpret_cast<const DictionaryValue*>(a);
+ const DictionaryValue* b_dict = reinterpret_cast<const DictionaryValue*>(b);
+ string16 a_str;
+ string16 b_str;
+ a_dict->GetString(kNameId, &a_str);
+ b_dict->GetString(kNameId, &b_str);
+ if (collator_ == NULL)
+ return a_str < b_str;
+ return l10n_util::CompareString16WithCollator(
+ collator_, a_str, b_str) == UCOL_LESS;
+ }
+
+ icu::Collator* collator_;
+};
+
+} // namespace
+
+CertificateManagerHandler::CertificateManagerHandler() {
+ certificate_manager_model_.reset(new CertificateManagerModel);
+}
+
+CertificateManagerHandler::~CertificateManagerHandler() {
+}
+
+void CertificateManagerHandler::GetLocalizedValues(
+ DictionaryValue* localized_strings) {
+ DCHECK(localized_strings);
+
+ localized_strings->SetString("certificateManagerPage",
+ l10n_util::GetStringUTF16(IDS_CERTIFICATE_MANAGER_TITLE));
+
+ // Tabs.
+ localized_strings->SetString("personalCertsTabTitle",
+ l10n_util::GetStringUTF16(IDS_CERT_MANAGER_PERSONAL_CERTS_TAB_LABEL));
+ localized_strings->SetString("emailCertsTabTitle",
+ l10n_util::GetStringUTF16(
+ IDS_CERT_MANAGER_OTHER_PEOPLES_CERTS_TAB_LABEL));
+ localized_strings->SetString("serverCertsTabTitle",
+ l10n_util::GetStringUTF16(IDS_CERT_MANAGER_SERVER_CERTS_TAB_LABEL));
+ localized_strings->SetString("caCertsTabTitle",
+ l10n_util::GetStringUTF16(IDS_CERT_MANAGER_CERT_AUTHORITIES_TAB_LABEL));
+ localized_strings->SetString("unknownCertsTabTitle",
+ l10n_util::GetStringUTF16(IDS_CERT_MANAGER_UNKNOWN_TAB_LABEL));
+
+ // Tab descriptions.
+ localized_strings->SetString("personalCertsTabDescription",
+ l10n_util::GetStringUTF16(IDS_CERT_MANAGER_USER_TREE_DESCRIPTION));
+ localized_strings->SetString("emailCertsTabDescription",
+ l10n_util::GetStringUTF16(
+ IDS_CERT_MANAGER_OTHER_PEOPLE_TREE_DESCRIPTION));
+ localized_strings->SetString("serverCertsTabDescription",
+ l10n_util::GetStringUTF16(IDS_CERT_MANAGER_SERVER_TREE_DESCRIPTION));
+ localized_strings->SetString("caCertsTabDescription",
+ l10n_util::GetStringUTF16(IDS_CERT_MANAGER_AUTHORITIES_TREE_DESCRIPTION));
+ localized_strings->SetString("unknownCertsTabDescription",
+ l10n_util::GetStringUTF16(IDS_CERT_MANAGER_UNKNOWN_TREE_DESCRIPTION));
+
+ // Tree columns.
+ localized_strings->SetString("certNameColumn",
+ l10n_util::GetStringUTF16(IDS_CERT_MANAGER_NAME_COLUMN_LABEL));
+ localized_strings->SetString("certDeviceColumn",
+ l10n_util::GetStringUTF16(IDS_CERT_MANAGER_DEVICE_COLUMN_LABEL));
+ localized_strings->SetString("certSerialColumn",
+ l10n_util::GetStringUTF16(IDS_CERT_MANAGER_SERIAL_NUMBER_COLUMN_LABEL));
+ localized_strings->SetString("certExpiresColumn",
+ l10n_util::GetStringUTF16(IDS_CERT_MANAGER_EXPIRES_COLUMN_LABEL));
+ localized_strings->SetString("certEmailColumn",
+ l10n_util::GetStringUTF16(IDS_CERT_MANAGER_EMAIL_ADDRESS_COLUMN_LABEL));
+
+ // Buttons.
+ localized_strings->SetString("view_certificate",
+ l10n_util::GetStringUTF16(IDS_CERT_MANAGER_VIEW_CERT_BUTTON));
+}
+
+void CertificateManagerHandler::RegisterMessages() {
+ dom_ui_->RegisterMessageCallback("viewCertificate",
+ NewCallback(this, &CertificateManagerHandler::View));
+
+ dom_ui_->RegisterMessageCallback("populateCertificateManager",
+ NewCallback(this, &CertificateManagerHandler::Populate));
+}
+
+void CertificateManagerHandler::View(const ListValue* args) {
+ std::string node_id;
+ if (!args->GetString(0, &node_id)){
+ return;
+ }
+ net::X509Certificate* cert = IdToCert(node_id);
+ if (!cert) {
+ NOTREACHED();
+ return;
+ }
+ ShowCertificateViewer(
+ dom_ui_->tab_contents()->view()->GetTopLevelNativeWindow(), cert);
+}
+
+void CertificateManagerHandler::Populate(const ListValue* args) {
+ certificate_manager_model_->Refresh();
+
+ PopulateTree("personalCertsTab", net::USER_CERT);
+ PopulateTree("emailCertsTab", net::EMAIL_CERT);
+ PopulateTree("serverCertsTab", net::SERVER_CERT);
+ PopulateTree("caCertsTab", net::CA_CERT);
+ PopulateTree("otherCertsTab", net::UNKNOWN_CERT);
+}
+
+void CertificateManagerHandler::PopulateTree(const std::string& tab_name,
+ net::CertType type) {
+ const std::string tree_name = tab_name + "-tree";
+
+ scoped_ptr<icu::Collator> collator;
+ UErrorCode error = U_ZERO_ERROR;
+ collator.reset(
+ icu::Collator::createInstance(
+ icu::Locale(g_browser_process->GetApplicationLocale().c_str()),
+ error));
+ if (U_FAILURE(error))
+ collator.reset(NULL);
+ DictionaryIdComparator comparator(collator.get());
+ CertificateManagerModel::OrgGroupingMap map;
+
+ certificate_manager_model_->FilterAndBuildOrgGroupingMap(type, &map);
+
+ {
+ ListValue* nodes = new ListValue;
+ for (CertificateManagerModel::OrgGroupingMap::iterator i = map.begin();
+ i != map.end(); ++i) {
+ // Populate first level (org name).
+ DictionaryValue* dict = new DictionaryValue;
+ dict->SetString(kKeyId, OrgNameToId(i->first));
+ dict->SetString(kNameId, i->first);
+
+ // Populate second level (certs).
+ ListValue* subnodes = new ListValue;
+ for (net::CertificateList::const_iterator org_cert_it = i->second.begin();
+ org_cert_it != i->second.end(); ++org_cert_it) {
+ DictionaryValue* cert_dict = new DictionaryValue;
+ net::X509Certificate* cert = org_cert_it->get();
+ cert_dict->SetString(kKeyId, CertToId(*cert));
+ cert_dict->SetString(kNameId, certificate_manager_model_->GetColumnText(
+ *cert, CertificateManagerModel::COL_SUBJECT_NAME));
+ // TODO(mattm): Other columns.
+ // TODO(mattm): Get a real icon (or figure out how to make the domui
+ // tree not use icons at all).
+ cert_dict->SetString(kIconId, "chrome://theme/IDR_COOKIE_ICON");
+ subnodes->Append(cert_dict);
+ }
+ std::sort(subnodes->begin(), subnodes->end(), comparator);
+
+ dict->Set(kSubNodesId, subnodes);
+ nodes->Append(dict);
+ }
+ std::sort(nodes->begin(), nodes->end(), comparator);
+
+ ListValue args;
+ args.Append(Value::CreateStringValue(tree_name));
+ args.Append(nodes);
+ dom_ui_->CallJavascriptFunction(L"CertificateManager.onPopulateTree", args);
+ }
+}
diff --git a/chrome/browser/dom_ui/certificate_manager_handler.h b/chrome/browser/dom_ui/certificate_manager_handler.h
new file mode 100644
index 0000000..265dba4
--- /dev/null
+++ b/chrome/browser/dom_ui/certificate_manager_handler.h
@@ -0,0 +1,40 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_DOM_UI_CERTIFICATE_MANAGER_HANDLER_H_
+#define CHROME_BROWSER_DOM_UI_CERTIFICATE_MANAGER_HANDLER_H_
+#pragma once
+
+#include "base/scoped_ptr.h"
+#include "chrome/browser/dom_ui/options_ui.h"
+#include "net/base/cert_database.h"
+
+class CertificateManagerModel;
+
+class CertificateManagerHandler : public OptionsPageUIHandler {
+ public:
+ CertificateManagerHandler();
+ virtual ~CertificateManagerHandler();
+
+ // OptionsUIHandler implementation.
+ virtual void GetLocalizedValues(DictionaryValue* localized_strings);
+ virtual void RegisterMessages();
+
+ private:
+ // View certificate.
+ void View(const ListValue* args);
+
+ // Populate the trees in all the tabs.
+ void Populate(const ListValue* args);
+
+ // Populate the given tab's tree.
+ void PopulateTree(const std::string& tab_name, net::CertType type);
+
+ // The Certificates Manager model
+ scoped_ptr<CertificateManagerModel> certificate_manager_model_;
+
+ DISALLOW_COPY_AND_ASSIGN(CertificateManagerHandler);
+};
+
+#endif // CHROME_BROWSER_DOM_UI_CERTIFICATE_MANAGER_HANDLER_H_
diff --git a/chrome/browser/dom_ui/options_ui.cc b/chrome/browser/dom_ui/options_ui.cc
index cb7830a..0ebeba8 100644
--- a/chrome/browser/dom_ui/options_ui.cc
+++ b/chrome/browser/dom_ui/options_ui.cc
@@ -65,6 +65,10 @@
#include "chrome/browser/chromeos/dom_ui/system_options_handler.h"
#endif
+#if defined(USE_NSS)
+#include "chrome/browser/dom_ui/certificate_manager_handler.h"
+#endif
+
////////////////////////////////////////////////////////////////////////////////
//
// OptionsUIHTMLSource
@@ -162,6 +166,9 @@ OptionsUI::OptionsUI(TabContents* contents) : DOMUI(contents) {
AddOptionsPageUIHandler(localized_strings, new chromeos::ProxyHandler());
AddOptionsPageUIHandler(localized_strings, new SystemOptionsHandler());
#endif
+#if defined(USE_NSS)
+ AddOptionsPageUIHandler(localized_strings, new CertificateManagerHandler());
+#endif
// |localized_strings| ownership is taken over by this constructor.
OptionsUIHTMLSource* html_source =
diff --git a/chrome/browser/resources/options.html b/chrome/browser/resources/options.html
index 74cd3bc..d6be2f9f 100644
--- a/chrome/browser/resources/options.html
+++ b/chrome/browser/resources/options.html
@@ -34,6 +34,10 @@
<link rel="stylesheet" href="options/chromeos_language_options.css">
</if>
+<if expr="not pp_ifdef('win32') and not pp_ifdef('darwin')">
+ <link rel="stylesheet" href="options/certificate_manager.css">
+</if>
+
<script src="chrome://resources/css/tree.css.js"></script>
<script src="chrome://resources/js/class_list.js"></script>
@@ -75,6 +79,13 @@
var SystemOptions = options.SystemOptions;
</script>
</if>
+<if expr="not pp_ifdef('win32') and not pp_ifdef('darwin')">
+ <script src="options/certificate_tree.js"></script>
+ <script src="options/certificate_manager.js"></script>
+ <script>
+ var CertificateManager = options.CertificateManager;
+ </script>
+</if>
<script src="options/add_startup_page_overlay.js"></script>
<script src="options/add_startup_page_recent_pages_list.js"></script>
<script src="options/advanced_options.js"></script>
@@ -146,6 +157,9 @@ function load() {
OptionsPage.registerSubPage(PasswordsExceptions.getInstance());
OptionsPage.registerSubPage(SearchEngineManager.getInstance());
OptionsPage.registerSubPage(SyncOptions.getInstance());
+ if (!cr.isWindows && !cr.isMac) {
+ OptionsPage.registerSubPage(CertificateManager.getInstance());
+ }
OptionsPage.registerOverlay(AddStartupPageOverlay.getInstance());
OptionsPage.registerOverlay(AlertOverlay.getInstance());
OptionsPage.registerOverlay(AutoFillEditAddressOverlay.getInstance());
@@ -275,6 +289,9 @@ window.onpopstate = function(e) {
<include src="options/chromeos_accounts_options.html">
<include src="options/chromeos_proxy.html">
</if>
+ <if expr="not pp_ifdef('win32') and not pp_ifdef('darwin')">
+ <include src="options/certificate_manager.html">
+ </if>
<include src="options/advanced_options.html">
<include src="options/autofill_options.html">
<include src="options/browser_options.html">
diff --git a/chrome/browser/resources/options/advanced_options.html b/chrome/browser/resources/options/advanced_options.html
index 8faf6ed..349ed38 100644
--- a/chrome/browser/resources/options/advanced_options.html
+++ b/chrome/browser/resources/options/advanced_options.html
@@ -90,14 +90,12 @@
</if>
</div>
</section>
-<if expr="not pp_ifdef('chromeos')">
<section>
<h3 i18n-content="advancedSectionTitleSecurity"></h3>
<div>
<div i18n-content="certificatesLabel"></div>
<div><button id="certificatesManageButton"
i18n-content="certificatesManageButton"></button></div>
-</if>
<if expr="os == 'win32'">
<!-- Configure these options for manual handling on windows -->
<label><input id="sslCheckRevocation"
@@ -123,9 +121,9 @@
pref="ssl.tls1.enabled" metric="Options_TLS1" type="checkbox"><span
i18n-content="sslUseTLS1"></span></label>
</if>
-<if expr="not pp_ifdef('chromeos')">
</div>
</section>
+<if expr="not pp_ifdef('chromeos')">
<section id="background-mode-section">
<h3 i18n-content="advancedSectionTitleChromeApps"></h3>
<div>
diff --git a/chrome/browser/resources/options/advanced_options.js b/chrome/browser/resources/options/advanced_options.js
index 64011ce..dabb324 100644
--- a/chrome/browser/resources/options/advanced_options.js
+++ b/chrome/browser/resources/options/advanced_options.js
@@ -54,6 +54,18 @@ var OptionsPage = options.OptionsPage;
OptionsPage.showPageByName('fontSettings');
chrome.send('coreOptionsUserMetricsAction', ['Options_FontSettings']);
};
+ if (cr.isWindows || cr.isMac) {
+ $('certificatesManageButton').onclick = function(event) {
+ chrome.send('showManageSSLCertificates');
+ };
+ } else {
+ $('certificatesManageButton').onclick = function(event) {
+ OptionsPage.showPageByName('certificateManager');
+ OptionsPage.showTab($('personal-certs-nav-tab'));
+ chrome.send('coreOptionsUserMetricsAction',
+ ['Options_ManageSSLCertificates']);
+ };
+ }
if (!cr.isChromeOS) {
$('optionsReset').onclick = function(event) {
AlertOverlay.show(undefined,
@@ -65,9 +77,6 @@ var OptionsPage = options.OptionsPage;
$('proxiesConfigureButton').onclick = function(event) {
chrome.send('showNetworkProxySettings');
};
- $('certificatesManageButton').onclick = function(event) {
- chrome.send('showManageSSLCertificates');
- };
$('downloadLocationBrowseButton').onclick = function(event) {
chrome.send('selectDownloadLocation');
};
diff --git a/chrome/browser/resources/options/certificate_manager.css b/chrome/browser/resources/options/certificate_manager.css
new file mode 100644
index 0000000..a88d231
--- /dev/null
+++ b/chrome/browser/resources/options/certificate_manager.css
@@ -0,0 +1,15 @@
+/*
+Copyright (c) 2010 The Chromium Authors. All rights reserved.
+Use of this source code is governed by a BSD-style license that can be
+found in the LICENSE file.
+*/
+
+.certificate-tree-table {
+ width: 100%;
+}
+
+.certificate-tree {
+ /* TODO(mattm): BLAH. Make this not statically sized. */
+ height: 300px;
+}
+
diff --git a/chrome/browser/resources/options/certificate_manager.html b/chrome/browser/resources/options/certificate_manager.html
new file mode 100644
index 0000000..32821f2
--- /dev/null
+++ b/chrome/browser/resources/options/certificate_manager.html
@@ -0,0 +1,106 @@
+<div class="page hidden" id="certificateManagerPage">
+ <h1>
+ <span i18n-content="advancedPage"></span>
+ &gt;
+ <span i18n-content="certificateManagerPage"></span>
+ </h1>
+
+ <!-- Navigation tabs -->
+ <div class="subpages-nav-tabs">
+ <span i18n-content="personalCertsTabTitle" id="personal-certs-nav-tab"
+ class="inactive-tab" tab-contents="personalCertsTab"></span><span
+ i18n-content="emailCertsTabTitle" id="email-certs-nav-tab"
+ class="inactive-tab" tab-contents="emailCertsTab"></span><span
+ i18n-content="serverCertsTabTitle" id="server-certs-nav-tab"
+ class="inactive-tab" tab-contents="serverCertsTab"></span><span
+ i18n-content="caCertsTabTitle" id="ca-certs-nav-tab"
+ class="inactive-tab" tab-contents="caCertsTab"></span><span
+ i18n-content="unknownCertsTabTitle" id="other-certs-nav-tab"
+ class="inactive-tab" tab-contents="otherCertsTab"></span>
+ </div>
+
+ <!-- TODO(mattm): get rid of use of tables? -->
+
+ <!-- Tab contents -->
+ <div id="personalCertsTab" class="subpages-tab-contents">
+ <table class="certificate-tree-table">
+ <tr><td>
+ <span i18n-content="personalCertsTabDescription"></span>
+ </td></tr>
+ <tr><td>
+ <tree id="personalCertsTab-tree" class="certificate-tree"></tree>
+ </td></tr>
+ <tr><td>
+ <button id="personalCertsTab-view" i18n-content="view_certificate"
+ disabled></button>
+ <!-- TODO other buttons -->
+ </td></tr>
+ </table>
+ </div>
+
+ <div id="emailCertsTab" class="subpages-tab-contents">
+ <table class="certificate-tree-table">
+ <tr><td>
+ <span i18n-content="emailCertsTabDescription"></span>
+ </td></tr>
+ <tr><td>
+ <tree id="emailCertsTab-tree" class="certificate-tree"></tree>
+ </td></tr>
+ <tr><td>
+ <button id="emailCertsTab-view" i18n-content="view_certificate"
+ disabled></button>
+ <!-- TODO other buttons -->
+ </td></tr>
+ </table>
+ </div>
+
+ <div id="serverCertsTab" class="subpages-tab-contents">
+ <table class="certificate-tree-table">
+ <tr><td>
+ <span i18n-content="serverCertsTabDescription"></span>
+ </td></tr>
+ <tr><td>
+ <tree id="serverCertsTab-tree" class="certificate-tree"></tree>
+ </td></tr>
+ <tr><td>
+ <button id="serverCertsTab-view" i18n-content="view_certificate"
+ disabled></button>
+ <!-- TODO other buttons -->
+ </td></tr>
+ </table>
+ </div>
+
+ <div id="caCertsTab" class="subpages-tab-contents">
+ <table class="certificate-tree-table">
+ <tr><td>
+ <span i18n-content="caCertsTabDescription"></span>
+ </td></tr>
+ <tr><td>
+ <tree id="caCertsTab-tree" class="certificate-tree"></tree>
+ </td></tr>
+ <tr><td>
+ <button id="caCertsTab-view" i18n-content="view_certificate"
+ disabled></button>
+ <!-- TODO other buttons -->
+ </td></tr>
+ </table>
+ </div>
+
+ <div id="otherCertsTab" class="subpages-tab-contents">
+ <table class="certificate-tree-table">
+ <tr><td>
+ <span i18n-content="unknownCertsTabDescription"></span>
+ </td></tr>
+ <tr><td>
+ <tree id="otherCertsTab-tree" class="certificate-tree"></tree>
+ </td></tr>
+ <tr><td>
+ <button id="otherCertsTab-view" i18n-content="view_certificate"
+ disabled></button>
+ <!-- TODO other buttons -->
+ </td></tr>
+ </table>
+ </div>
+
+</div>
+
diff --git a/chrome/browser/resources/options/certificate_manager.js b/chrome/browser/resources/options/certificate_manager.js
new file mode 100644
index 0000000..741809e
--- /dev/null
+++ b/chrome/browser/resources/options/certificate_manager.js
@@ -0,0 +1,117 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+cr.define('options', function() {
+
+ var OptionsPage = options.OptionsPage;
+
+ /////////////////////////////////////////////////////////////////////////////
+ // CertificateManagerTab class:
+
+ /**
+ * blah
+ * @param {!string} id The id of this tab.
+ */
+ function CertificateManagerTab(id) {
+ this.tree = $(id + '-tree');
+
+ options.CertificatesTree.decorate(this.tree);
+ this.tree.addEventListener('change',
+ this.handleCertificatesTreeChange_.bind(this));
+
+
+ this.viewButton = $(id + '-view');
+
+ var tree = this.tree;
+ this.viewButton.onclick = function(e) {
+ var selected = tree.selectedItem;
+ chrome.send('viewCertificate', [selected.data.id]);
+ }
+ }
+
+ CertificateManagerTab.prototype = {
+
+ /**
+ * Update button state.
+ * @private
+ * @param {!Object} data The data of the selected item.
+ */
+ updateButtonState: function(data) {
+ var isCert = !!data && data.id.substr(0, 5) == 'cert-';
+ this.viewButton.disabled = !isCert;
+ },
+
+ /**
+ * Handles certificate tree selection change.
+ * @private
+ * @param {!Event} e The change event object.
+ */
+ handleCertificatesTreeChange_: function(e) {
+ var data = null;
+ if (this.tree.selectedItem) {
+ data = this.tree.selectedItem.data;
+ }
+
+ this.updateButtonState(data);
+ },
+
+ }
+
+ /////////////////////////////////////////////////////////////////////////////
+ // CertificateManager class:
+
+ /**
+ * Encapsulated handling of ChromeOS accounts options page.
+ * @constructor
+ */
+ function CertificateManager(model) {
+ OptionsPage.call(this, 'certificateManager',
+ localStrings.getString('certificateManagerPage'),
+ 'certificateManagerPage');
+ }
+
+ cr.addSingletonGetter(CertificateManager);
+
+ CertificateManager.prototype = {
+ __proto__: OptionsPage.prototype,
+
+ initializePage: function() {
+ OptionsPage.prototype.initializePage.call(this);
+
+ this.personalTab = new CertificateManagerTab('personalCertsTab');
+ this.emailTab = new CertificateManagerTab('emailCertsTab');
+ this.serverTab = new CertificateManagerTab('serverCertsTab');
+ this.caTab = new CertificateManagerTab('caCertsTab');
+ this.otherTab = new CertificateManagerTab('otherCertsTab');
+
+ this.addEventListener('visibleChange', this.handleVisibleChange_);
+ },
+
+ initalized_: false,
+
+ /**
+ * Handler for OptionsPage's visible property change event.
+ * @private
+ * @param {Event} e Property change event.
+ */
+ handleVisibleChange_: function(e) {
+ if (!this.initalized_ && this.visible) {
+ this.initalized_ = true;
+ chrome.send('populateCertificateManager');
+ }
+ }
+ };
+
+ // CertificateManagerHandler callbacks.
+ CertificateManager.onPopulateTree = function(args) {
+ $(args[0]).populate(args[1]);
+ };
+
+ // Export
+ return {
+ CertificateManagerTab: CertificateManagerTab,
+ CertificateManager: CertificateManager
+ };
+
+});
diff --git a/chrome/browser/resources/options/certificate_tree.js b/chrome/browser/resources/options/certificate_tree.js
new file mode 100644
index 0000000..f8ac854
--- /dev/null
+++ b/chrome/browser/resources/options/certificate_tree.js
@@ -0,0 +1,120 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+cr.define('options', function() {
+ const Tree = cr.ui.Tree;
+ const TreeItem = cr.ui.TreeItem;
+
+ /**
+ * Creates a new tree item for certificate data.
+ * @param {Object=} data Data used to create a certificate tree item.
+ * @constructor
+ * @extends {TreeItem}
+ */
+ function CertificateTreeItem(data) {
+ // TODO(mattm): other columns
+ var treeItem = new TreeItem({
+ label: data.name,
+ data: data
+ });
+ treeItem.__proto__ = CertificateTreeItem.prototype;
+
+ if (data.icon) {
+ treeItem.icon = data.icon;
+ }
+
+ return treeItem;
+ }
+
+ CertificateTreeItem.prototype = {
+ __proto__: TreeItem.prototype,
+
+ /**
+ * The tree path id/.
+ * @type {string}
+ */
+ get pathId() {
+ var parent = this.parentItem;
+ if (parent && parent instanceof CertificateTreeItem) {
+ return parent.pathId + ',' + this.data.id;
+ } else {
+ return this.data.id;
+ }
+ }
+ };
+
+ /**
+ * Creates a new cookies tree.
+ * @param {Object=} opt_propertyBag Optional properties.
+ * @constructor
+ * @extends {Tree}
+ */
+ var CertificatesTree = cr.ui.define('tree');
+
+ CertificatesTree.prototype = {
+ __proto__: Tree.prototype,
+
+ /** @inheritDoc */
+ decorate: function() {
+ Tree.prototype.decorate.call(this);
+ this.treeLookup_ = {};
+ },
+
+ /** @inheritDoc */
+ addAt: function(child, index) {
+ Tree.prototype.addAt.call(this, child, index);
+ if (child.data && child.data.id)
+ this.treeLookup_[child.data.id] = child;
+ },
+
+ /** @inheritDoc */
+ remove: function(child) {
+ Tree.prototype.remove.call(this, child);
+ if (child.data && child.data.id)
+ delete this.treeLookup_[child.data.id];
+ },
+
+ /**
+ * Clears the tree.
+ */
+ clear: function() {
+ // Remove all fields without recreating the object since other code
+ // references it.
+ for (var id in this.treeLookup_){
+ delete this.treeLookup_[id];
+ }
+ this.textContent = '';
+ },
+
+ /**
+ * Populate the tree.
+ * @param {Array} nodesData Nodes data array.
+ */
+ populate: function(nodesData) {
+ this.clear();
+
+ for (var i = 0; i < nodesData.length; ++i) {
+ var subnodes = nodesData[i]['subnodes'];
+ delete nodesData[i]['subnodes'];
+
+ var item = new CertificateTreeItem(nodesData[i]);
+ this.addAt(item, i);
+
+ for (var j = 0; j < subnodes.length; ++j) {
+ var subitem = new CertificateTreeItem(subnodes[j]);
+ item.addAt(subitem, j);
+ }
+ // Make tree expanded by default.
+ item.expanded = true;
+ }
+
+ cr.dispatchSimpleEvent(this, 'change');
+ },
+ };
+
+ return {
+ CertificatesTree: CertificatesTree
+ };
+});
+
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index df077d3..27753ba 100644
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -345,6 +345,8 @@
'browser/cancelable_request.h',
'browser/cert_store.cc',
'browser/cert_store.h',
+ 'browser/certificate_manager_model.cc',
+ 'browser/certificate_manager_model.h',
'browser/certificate_viewer.cc',
'browser/certificate_viewer.h',
'browser/character_encoding.cc',
@@ -1230,6 +1232,8 @@
'browser/dom_ui/advanced_options_utils_win.cc',
'browser/dom_ui/browser_options_handler.cc',
'browser/dom_ui/browser_options_handler.h',
+ 'browser/dom_ui/certificate_manager_handler.cc',
+ 'browser/dom_ui/certificate_manager_handler.h',
'browser/dom_ui/clear_browser_data_handler.cc',
'browser/dom_ui/clear_browser_data_handler.h',
'browser/dom_ui/content_settings_handler.cc',
@@ -3301,6 +3305,11 @@
],
}, { # OS != "linux"
'sources!': [
+ # TODO(mattm): Cert manager stuff is really !USE_NSS.
+ 'browser/certificate_manager_model.cc',
+ 'browser/certificate_manager_model.h',
+ 'browser/dom_ui/certificate_manager_handler.cc',
+ 'browser/dom_ui/certificate_manager_handler.h',
'browser/file_path_watcher_inotify.cc',
],
}],