| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2010 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/gtk/certificate_manager.h" | |
| 6 | |
| 7 #include <cert.h> | |
| 8 #include <gtk/gtk.h> | |
| 9 #include <pk11pub.h> | |
| 10 | |
| 11 #include <map> | |
| 12 #include <string> | |
| 13 | |
| 14 #include "app/gtk_signal.h" | |
| 15 #include "app/l10n_util.h" | |
| 16 #include "app/l10n_util_collator.h" | |
| 17 #include "base/gtk_util.h" | |
| 18 #include "base/i18n/time_formatting.h" | |
| 19 #include "base/nss_util.h" | |
| 20 #include "chrome/browser/browser_process.h" | |
| 21 #include "chrome/browser/gtk/certificate_viewer.h" | |
| 22 #include "chrome/browser/gtk/gtk_util.h" | |
| 23 #include "chrome/browser/prefs/pref_member.h" | |
| 24 #include "chrome/browser/prefs/pref_service.h" | |
| 25 #include "chrome/browser/profile.h" | |
| 26 #include "chrome/common/pref_names.h" | |
| 27 #include "chrome/third_party/mozilla_security_manager/nsNSSCertHelper.h" | |
| 28 #include "chrome/third_party/mozilla_security_manager/nsNSSCertificate.h" | |
| 29 #include "grit/generated_resources.h" | |
| 30 | |
| 31 // PSM = Mozilla's Personal Security Manager. | |
| 32 namespace psm = mozilla_security_manager; | |
| 33 | |
| 34 namespace { | |
| 35 | |
| 36 // Convert a char* return value from NSS into a std::string and free the NSS | |
| 37 // memory. If the arg is NULL, an empty string will be returned instead. | |
| 38 std::string Stringize(char* nss_text) { | |
| 39 std::string s; | |
| 40 if (nss_text) { | |
| 41 s = nss_text; | |
| 42 PORT_Free(nss_text); | |
| 43 } | |
| 44 return s; | |
| 45 } | |
| 46 | |
| 47 //////////////////////////////////////////////////////////////////////////////// | |
| 48 // CertificatePage class definition. | |
| 49 | |
| 50 class CertificatePage { | |
| 51 public: | |
| 52 explicit CertificatePage(net::CertType type); | |
| 53 virtual ~CertificatePage() {} | |
| 54 | |
| 55 void PopulateTree(CERTCertList* cert_list); | |
| 56 | |
| 57 // Get the top-level widget of this page. | |
| 58 GtkWidget* widget() { return vbox_; } | |
| 59 | |
| 60 private: | |
| 61 // Columns of the tree store. | |
| 62 enum { | |
| 63 CERT_NAME, | |
| 64 CERT_SECURITY_DEVICE, | |
| 65 CERT_SERIAL_NUMBER, | |
| 66 CERT_EXPIRES_ON, | |
| 67 CERT_EXPIRES_ON_INT, | |
| 68 CERT_ADDRESS, | |
| 69 CERT_POINTER, | |
| 70 CERT_STORE_NUM_COLUMNS | |
| 71 }; | |
| 72 | |
| 73 gint LocaleSortFunc(GtkTreeModel* model, GtkTreeIter* a, GtkTreeIter* b, | |
| 74 int col); | |
| 75 | |
| 76 // Gtk event callbacks. | |
| 77 CHROMEG_CALLBACK_2(CertificatePage, gint, SortNameFunc, GtkTreeModel*, | |
| 78 GtkTreeIter*, GtkTreeIter*); | |
| 79 CHROMEG_CALLBACK_2(CertificatePage, gint, SortDeviceFunc, GtkTreeModel*, | |
| 80 GtkTreeIter*, GtkTreeIter*); | |
| 81 CHROMEG_CALLBACK_0(CertificatePage, void, OnSelectionChanged, | |
| 82 GtkTreeSelection*); | |
| 83 CHROMEGTK_CALLBACK_0(CertificatePage, void, OnViewClicked); | |
| 84 | |
| 85 net::CertType type_; | |
| 86 | |
| 87 // The top-level widget of this page. | |
| 88 GtkWidget* vbox_; | |
| 89 | |
| 90 GtkWidget* tree_; | |
| 91 GtkTreeStore* store_; | |
| 92 GtkTreeSelection* selection_; | |
| 93 scoped_ptr<icu::Collator> collator_; | |
| 94 | |
| 95 GtkWidget* view_button_; | |
| 96 }; | |
| 97 | |
| 98 //////////////////////////////////////////////////////////////////////////////// | |
| 99 // CertificatePage implementation. | |
| 100 | |
| 101 CertificatePage::CertificatePage(net::CertType type) : type_(type) { | |
| 102 vbox_ = gtk_vbox_new(FALSE, gtk_util::kControlSpacing); | |
| 103 gtk_container_set_border_width(GTK_CONTAINER(vbox_), | |
| 104 gtk_util::kContentAreaBorder); | |
| 105 | |
| 106 static const int kDescriptionIds[] = { | |
| 107 IDS_CERT_MANAGER_USER_TREE_DESCRIPTION, | |
| 108 IDS_CERT_MANAGER_OTHER_PEOPLE_TREE_DESCRIPTION, | |
| 109 IDS_CERT_MANAGER_SERVER_TREE_DESCRIPTION, | |
| 110 IDS_CERT_MANAGER_AUTHORITIES_TREE_DESCRIPTION, | |
| 111 IDS_CERT_MANAGER_UNKNOWN_TREE_DESCRIPTION, | |
| 112 }; | |
| 113 DCHECK_EQ(arraysize(kDescriptionIds), | |
| 114 static_cast<size_t>(net::NUM_CERT_TYPES)); | |
| 115 GtkWidget* description_label = gtk_label_new(l10n_util::GetStringUTF8( | |
| 116 kDescriptionIds[type]).c_str()); | |
| 117 gtk_util::LeftAlignMisc(description_label); | |
| 118 gtk_box_pack_start(GTK_BOX(vbox_), description_label, FALSE, FALSE, 0); | |
| 119 | |
| 120 store_ = gtk_tree_store_new(CERT_STORE_NUM_COLUMNS, | |
| 121 G_TYPE_STRING, | |
| 122 G_TYPE_STRING, | |
| 123 G_TYPE_STRING, | |
| 124 G_TYPE_STRING, | |
| 125 G_TYPE_INT64, | |
| 126 G_TYPE_STRING, | |
| 127 G_TYPE_POINTER); | |
| 128 tree_ = gtk_tree_view_new_with_model(GTK_TREE_MODEL(store_)); | |
| 129 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(tree_), TRUE); | |
| 130 selection_ = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree_)); | |
| 131 gtk_tree_selection_set_mode(selection_, GTK_SELECTION_SINGLE); | |
| 132 g_signal_connect(selection_, "changed", G_CALLBACK(OnSelectionChangedThunk), | |
| 133 this); | |
| 134 | |
| 135 GtkTreeViewColumn* name_col = gtk_tree_view_column_new_with_attributes( | |
| 136 l10n_util::GetStringUTF8(IDS_CERT_MANAGER_NAME_COLUMN_LABEL).c_str(), | |
| 137 gtk_cell_renderer_text_new(), | |
| 138 "text", CERT_NAME, | |
| 139 NULL); | |
| 140 gtk_tree_view_column_set_sort_column_id(name_col, CERT_NAME); | |
| 141 gtk_tree_view_append_column(GTK_TREE_VIEW(tree_), name_col); | |
| 142 | |
| 143 if (type == net::USER_CERT || type == net::CA_CERT || | |
| 144 type == net::UNKNOWN_CERT) { | |
| 145 GtkTreeViewColumn* device_col = gtk_tree_view_column_new_with_attributes( | |
| 146 l10n_util::GetStringUTF8( | |
| 147 IDS_CERT_MANAGER_DEVICE_COLUMN_LABEL).c_str(), | |
| 148 gtk_cell_renderer_text_new(), | |
| 149 "text", CERT_SECURITY_DEVICE, | |
| 150 NULL); | |
| 151 gtk_tree_view_column_set_sort_column_id(device_col, CERT_SECURITY_DEVICE); | |
| 152 gtk_tree_view_append_column(GTK_TREE_VIEW(tree_), device_col); | |
| 153 } | |
| 154 | |
| 155 if (type == net::USER_CERT) { | |
| 156 GtkTreeViewColumn* serial_col = gtk_tree_view_column_new_with_attributes( | |
| 157 l10n_util::GetStringUTF8( | |
| 158 IDS_CERT_MANAGER_SERIAL_NUMBER_COLUMN_LABEL).c_str(), | |
| 159 gtk_cell_renderer_text_new(), | |
| 160 "text", CERT_SERIAL_NUMBER, | |
| 161 NULL); | |
| 162 gtk_tree_view_column_set_sort_column_id(serial_col, CERT_SERIAL_NUMBER); | |
| 163 gtk_tree_view_append_column(GTK_TREE_VIEW(tree_), serial_col); | |
| 164 } | |
| 165 | |
| 166 if (type == net::USER_CERT || type == net::EMAIL_CERT || | |
| 167 type == net::SERVER_CERT) { | |
| 168 GtkTreeViewColumn* expires_col = gtk_tree_view_column_new_with_attributes( | |
| 169 l10n_util::GetStringUTF8( | |
| 170 IDS_CERT_MANAGER_EXPIRES_COLUMN_LABEL).c_str(), | |
| 171 gtk_cell_renderer_text_new(), | |
| 172 "text", CERT_EXPIRES_ON, | |
| 173 NULL); | |
| 174 gtk_tree_view_column_set_sort_column_id(expires_col, CERT_EXPIRES_ON_INT); | |
| 175 gtk_tree_view_append_column(GTK_TREE_VIEW(tree_), expires_col); | |
| 176 } | |
| 177 | |
| 178 if (type == net::EMAIL_CERT) { | |
| 179 GtkTreeViewColumn* addr_col = gtk_tree_view_column_new_with_attributes( | |
| 180 l10n_util::GetStringUTF8( | |
| 181 IDS_CERT_MANAGER_EMAIL_ADDRESS_COLUMN_LABEL).c_str(), | |
| 182 gtk_cell_renderer_text_new(), | |
| 183 "text", CERT_ADDRESS, | |
| 184 NULL); | |
| 185 gtk_tree_view_column_set_sort_column_id(addr_col, CERT_ADDRESS); | |
| 186 gtk_tree_view_append_column(GTK_TREE_VIEW(tree_), addr_col); | |
| 187 } | |
| 188 | |
| 189 UErrorCode error = U_ZERO_ERROR; | |
| 190 collator_.reset( | |
| 191 icu::Collator::createInstance( | |
| 192 icu::Locale(g_browser_process->GetApplicationLocale().c_str()), | |
| 193 error)); | |
| 194 if (U_FAILURE(error)) | |
| 195 collator_.reset(NULL); | |
| 196 if (collator_ != NULL) { | |
| 197 gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(store_), CERT_NAME, | |
| 198 SortNameFuncThunk, this, NULL); | |
| 199 gtk_tree_sortable_set_sort_func(GTK_TREE_SORTABLE(store_), | |
| 200 CERT_SECURITY_DEVICE, SortDeviceFuncThunk, | |
| 201 this, NULL); | |
| 202 } | |
| 203 | |
| 204 gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(store_), CERT_NAME, | |
| 205 GTK_SORT_ASCENDING); | |
| 206 | |
| 207 GtkWidget* scroll_window = gtk_scrolled_window_new(NULL, NULL); | |
| 208 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll_window), | |
| 209 GTK_POLICY_AUTOMATIC, | |
| 210 GTK_POLICY_AUTOMATIC); | |
| 211 gtk_scrolled_window_set_shadow_type( | |
| 212 GTK_SCROLLED_WINDOW(scroll_window), GTK_SHADOW_ETCHED_IN); | |
| 213 gtk_container_add(GTK_CONTAINER(scroll_window), tree_); | |
| 214 gtk_box_pack_start(GTK_BOX(vbox_), scroll_window, TRUE, TRUE, 0); | |
| 215 | |
| 216 GtkWidget* button_box = gtk_hbox_new(FALSE, gtk_util::kControlSpacing); | |
| 217 gtk_box_pack_start(GTK_BOX(vbox_), button_box, FALSE, FALSE, 0); | |
| 218 | |
| 219 view_button_ = gtk_button_new_with_mnemonic( | |
| 220 gtk_util::ConvertAcceleratorsFromWindowsStyle( | |
| 221 l10n_util::GetStringUTF8( | |
| 222 IDS_CERT_MANAGER_VIEW_CERT_BUTTON)).c_str()); | |
| 223 gtk_widget_set_sensitive(view_button_, FALSE); | |
| 224 g_signal_connect(view_button_, "clicked", | |
| 225 G_CALLBACK(OnViewClickedThunk), this); | |
| 226 gtk_box_pack_start(GTK_BOX(button_box), view_button_, FALSE, FALSE, 0); | |
| 227 | |
| 228 // TODO(mattm): Add buttons for import, export, delete, etc | |
| 229 } | |
| 230 | |
| 231 void CertificatePage::PopulateTree(CERTCertList* cert_list) { | |
| 232 DCHECK(gtk_tree_model_get_flags(GTK_TREE_MODEL(store_)) & | |
| 233 GTK_TREE_MODEL_ITERS_PERSIST); | |
| 234 | |
| 235 typedef std::map<std::string, GtkTreeIter> OrgTreeMap; | |
| 236 OrgTreeMap org_tree_map; | |
| 237 | |
| 238 CERTCertListNode* node; | |
| 239 for (node = CERT_LIST_HEAD(cert_list); | |
| 240 !CERT_LIST_END(node, cert_list); | |
| 241 node = CERT_LIST_NEXT(node)) { | |
| 242 CERTCertificate* cert = node->cert; | |
| 243 net::CertType type = psm::GetCertType(cert); | |
| 244 if (type == type_) { | |
| 245 std::string org = Stringize(CERT_GetOrgName(&cert->subject)); | |
| 246 if (org.empty()) | |
| 247 org = Stringize(CERT_GetCommonName(&cert->subject)); | |
| 248 OrgTreeMap::iterator org_tree_map_iter = org_tree_map.find(org); | |
| 249 if (org_tree_map_iter == org_tree_map.end()) { | |
| 250 GtkTreeIter iter; | |
| 251 gtk_tree_store_append(store_, &iter, NULL); | |
| 252 gtk_tree_store_set(store_, &iter, CERT_NAME, org.c_str(), -1); | |
| 253 org_tree_map_iter = org_tree_map.insert(std::make_pair(org, | |
| 254 iter)).first; | |
| 255 } | |
| 256 std::string name = psm::ProcessIDN( | |
| 257 Stringize(CERT_GetCommonName(&cert->subject))); | |
| 258 if (name.empty() && cert->nickname) { | |
| 259 name = cert->nickname; | |
| 260 // Hack copied from mozilla: Cut off text before first :, which seems to | |
| 261 // just be the token name. | |
| 262 size_t colon_pos = name.find(':'); | |
| 263 if (colon_pos != std::string::npos) | |
| 264 name = name.substr(colon_pos + 1); | |
| 265 } | |
| 266 GtkTreeIter iter; | |
| 267 gtk_tree_store_append(store_, &iter, &org_tree_map_iter->second); | |
| 268 gtk_tree_store_set(store_, &iter, | |
| 269 CERT_NAME, name.c_str(), | |
| 270 CERT_SECURITY_DEVICE, | |
| 271 psm::GetCertTokenName(cert).c_str(), | |
| 272 CERT_SERIAL_NUMBER, | |
| 273 Stringize(CERT_Hexify( | |
| 274 &cert->serialNumber, TRUE)).c_str(), | |
| 275 CERT_ADDRESS, cert->emailAddr, | |
| 276 CERT_POINTER, cert, | |
| 277 -1); | |
| 278 | |
| 279 PRTime issued, expires; | |
| 280 if (CERT_GetCertTimes(cert, &issued, &expires) == SECSuccess) { | |
| 281 gtk_tree_store_set(store_, &iter, | |
| 282 CERT_EXPIRES_ON, | |
| 283 WideToUTF8(base::TimeFormatShortDateNumeric( | |
| 284 base::PRTimeToBaseTime(expires))).c_str(), | |
| 285 CERT_EXPIRES_ON_INT, expires, | |
| 286 -1); | |
| 287 } | |
| 288 } | |
| 289 } | |
| 290 | |
| 291 gtk_tree_view_expand_all(GTK_TREE_VIEW(tree_)); | |
| 292 } | |
| 293 | |
| 294 gint CertificatePage::LocaleSortFunc(GtkTreeModel* model, | |
| 295 GtkTreeIter* a, | |
| 296 GtkTreeIter* b, | |
| 297 int col) { | |
| 298 gchar* value1 = NULL; | |
| 299 gchar* value2 = NULL; | |
| 300 gtk_tree_model_get(model, a, col, &value1, -1); | |
| 301 gtk_tree_model_get(model, b, col, &value2, -1); | |
| 302 if (!value1 || !value2) { | |
| 303 if (value1) | |
| 304 return 1; | |
| 305 if (value2) | |
| 306 return -1; | |
| 307 return 0; | |
| 308 } | |
| 309 | |
| 310 return l10n_util::CompareStringWithCollator(collator_.get(), | |
| 311 UTF8ToWide(value1), | |
| 312 UTF8ToWide(value2)); | |
| 313 } | |
| 314 | |
| 315 gint CertificatePage::SortNameFunc(GtkTreeModel* model, GtkTreeIter* a, | |
| 316 GtkTreeIter* b) { | |
| 317 return LocaleSortFunc(model, a, b, CERT_NAME); | |
| 318 } | |
| 319 | |
| 320 gint CertificatePage::SortDeviceFunc(GtkTreeModel* model, GtkTreeIter* a, | |
| 321 GtkTreeIter* b) { | |
| 322 return LocaleSortFunc(model, a, b, CERT_SECURITY_DEVICE); | |
| 323 } | |
| 324 | |
| 325 void CertificatePage::OnSelectionChanged(GtkTreeSelection* selection) { | |
| 326 CERTCertificate* cert = NULL; | |
| 327 GtkTreeIter iter; | |
| 328 GtkTreeModel* model; | |
| 329 if (gtk_tree_selection_get_selected(selection_, &model, &iter)) | |
| 330 gtk_tree_model_get(model, &iter, CERT_POINTER, &cert, -1); | |
| 331 | |
| 332 gtk_widget_set_sensitive(view_button_, cert ? TRUE : FALSE); | |
| 333 } | |
| 334 | |
| 335 void CertificatePage::OnViewClicked(GtkWidget* button) { | |
| 336 GtkTreeIter iter; | |
| 337 GtkTreeModel* model; | |
| 338 if (!gtk_tree_selection_get_selected(selection_, &model, &iter)) | |
| 339 return; | |
| 340 | |
| 341 CERTCertificate* cert = NULL; | |
| 342 gtk_tree_model_get(model, &iter, CERT_POINTER, &cert, -1); | |
| 343 if (cert) | |
| 344 ShowCertificateViewer(GTK_WINDOW(gtk_widget_get_toplevel(widget())), cert); | |
| 345 } | |
| 346 | |
| 347 //////////////////////////////////////////////////////////////////////////////// | |
| 348 // CertificateManager class definition. | |
| 349 | |
| 350 class CertificateManager { | |
| 351 public: | |
| 352 explicit CertificateManager(gfx::NativeWindow parent, Profile* profile); | |
| 353 virtual ~CertificateManager(); | |
| 354 | |
| 355 // Shows the Tab corresponding to the specified |page|. | |
| 356 void ShowCertificatePage(CertificateManagerPage page); | |
| 357 | |
| 358 private: | |
| 359 CHROMEGTK_CALLBACK_2(CertificateManager, void, OnSwitchPage, | |
| 360 GtkNotebookPage*, guint); | |
| 361 | |
| 362 CERTCertList* cert_list_; | |
| 363 | |
| 364 CertificatePage user_page_; | |
| 365 CertificatePage email_page_; | |
| 366 CertificatePage server_page_; | |
| 367 CertificatePage ca_page_; | |
| 368 CertificatePage unknown_page_; | |
| 369 | |
| 370 GtkWidget* dialog_; | |
| 371 | |
| 372 GtkWidget* notebook_; | |
| 373 | |
| 374 // The last page the user was on when they opened the CertificateManager | |
| 375 // window. | |
| 376 IntegerPrefMember last_selected_page_; | |
| 377 | |
| 378 DISALLOW_COPY_AND_ASSIGN(CertificateManager); | |
| 379 }; | |
| 380 | |
| 381 //////////////////////////////////////////////////////////////////////////////// | |
| 382 // CertificateManager implementation. | |
| 383 | |
| 384 void OnDestroy(GtkDialog* dialog, CertificateManager* cert_manager) { | |
| 385 delete cert_manager; | |
| 386 } | |
| 387 | |
| 388 CertificateManager::CertificateManager(gfx::NativeWindow parent, | |
| 389 Profile* profile) | |
| 390 : user_page_(net::USER_CERT), | |
| 391 email_page_(net::EMAIL_CERT), | |
| 392 server_page_(net::SERVER_CERT), | |
| 393 ca_page_(net::CA_CERT), | |
| 394 unknown_page_(net::UNKNOWN_CERT) { | |
| 395 // We don't need to observe changes in this value. | |
| 396 last_selected_page_.Init(prefs::kCertificateManagerWindowLastTabIndex, | |
| 397 profile->GetPrefs(), NULL); | |
| 398 | |
| 399 dialog_ = gtk_dialog_new_with_buttons( | |
| 400 l10n_util::GetStringUTF8(IDS_CERTIFICATE_MANAGER_TITLE).c_str(), | |
| 401 parent, | |
| 402 // Non-modal. | |
| 403 GTK_DIALOG_NO_SEPARATOR, | |
| 404 GTK_STOCK_CLOSE, | |
| 405 GTK_RESPONSE_CLOSE, | |
| 406 NULL); | |
| 407 gtk_box_set_spacing(GTK_BOX(GTK_DIALOG(dialog_)->vbox), | |
| 408 gtk_util::kContentAreaSpacing); | |
| 409 gtk_window_set_default_size(GTK_WINDOW(dialog_), 600, 440); | |
| 410 | |
| 411 notebook_ = gtk_notebook_new(); | |
| 412 gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog_)->vbox), notebook_); | |
| 413 | |
| 414 gtk_notebook_append_page( | |
| 415 GTK_NOTEBOOK(notebook_), | |
| 416 user_page_.widget(), | |
| 417 gtk_label_new_with_mnemonic( | |
| 418 l10n_util::GetStringUTF8( | |
| 419 IDS_CERT_MANAGER_PERSONAL_CERTS_TAB_LABEL).c_str())); | |
| 420 | |
| 421 gtk_notebook_append_page( | |
| 422 GTK_NOTEBOOK(notebook_), | |
| 423 email_page_.widget(), | |
| 424 gtk_label_new_with_mnemonic( | |
| 425 l10n_util::GetStringUTF8( | |
| 426 IDS_CERT_MANAGER_OTHER_PEOPLES_CERTS_TAB_LABEL).c_str())); | |
| 427 | |
| 428 gtk_notebook_append_page( | |
| 429 GTK_NOTEBOOK(notebook_), | |
| 430 server_page_.widget(), | |
| 431 gtk_label_new_with_mnemonic( | |
| 432 l10n_util::GetStringUTF8( | |
| 433 IDS_CERT_MANAGER_SERVER_CERTS_TAB_LABEL).c_str())); | |
| 434 | |
| 435 gtk_notebook_append_page( | |
| 436 GTK_NOTEBOOK(notebook_), | |
| 437 ca_page_.widget(), | |
| 438 gtk_label_new_with_mnemonic( | |
| 439 l10n_util::GetStringUTF8( | |
| 440 IDS_CERT_MANAGER_CERT_AUTHORITIES_TAB_LABEL).c_str())); | |
| 441 | |
| 442 gtk_notebook_append_page( | |
| 443 GTK_NOTEBOOK(notebook_), | |
| 444 unknown_page_.widget(), | |
| 445 gtk_label_new_with_mnemonic( | |
| 446 l10n_util::GetStringUTF8( | |
| 447 IDS_CERT_MANAGER_UNKNOWN_TAB_LABEL).c_str())); | |
| 448 | |
| 449 cert_list_ = PK11_ListCerts(PK11CertListUnique, NULL); | |
| 450 user_page_.PopulateTree(cert_list_); | |
| 451 email_page_.PopulateTree(cert_list_); | |
| 452 server_page_.PopulateTree(cert_list_); | |
| 453 ca_page_.PopulateTree(cert_list_); | |
| 454 unknown_page_.PopulateTree(cert_list_); | |
| 455 | |
| 456 // Need to show the notebook before connecting switch-page signal, otherwise | |
| 457 // we'll immediately get a signal switching to page 0 and overwrite our | |
| 458 // last_selected_page_ value. | |
| 459 gtk_util::ShowDialogWithLocalizedSize(dialog_, -1, -1, true); | |
| 460 | |
| 461 g_signal_connect(notebook_, "switch-page", | |
| 462 G_CALLBACK(OnSwitchPageThunk), this); | |
| 463 | |
| 464 g_signal_connect(dialog_, "response", G_CALLBACK(gtk_widget_destroy), NULL); | |
| 465 g_signal_connect(dialog_, "destroy", G_CALLBACK(OnDestroy), this); | |
| 466 } | |
| 467 | |
| 468 CertificateManager::~CertificateManager() { | |
| 469 CERT_DestroyCertList(cert_list_); | |
| 470 } | |
| 471 | |
| 472 void CertificateManager::OnSwitchPage(GtkWidget* notebook, | |
| 473 GtkNotebookPage* page, | |
| 474 guint page_num) { | |
| 475 int index = static_cast<int>(page_num); | |
| 476 DCHECK(index > CERT_MANAGER_PAGE_DEFAULT && index < CERT_MANAGER_PAGE_COUNT); | |
| 477 last_selected_page_.SetValue(index); | |
| 478 } | |
| 479 | |
| 480 void CertificateManager::ShowCertificatePage(CertificateManagerPage page) { | |
| 481 // Bring options window to front if it already existed and isn't already | |
| 482 // in front | |
| 483 gtk_window_present_with_time(GTK_WINDOW(dialog_), | |
| 484 gtk_get_current_event_time()); | |
| 485 | |
| 486 if (page == CERT_MANAGER_PAGE_DEFAULT) { | |
| 487 // Remember the last visited page from local state. | |
| 488 page = static_cast<CertificateManagerPage>(last_selected_page_.GetValue()); | |
| 489 if (page == CERT_MANAGER_PAGE_DEFAULT) | |
| 490 page = CERT_MANAGER_PAGE_USER; | |
| 491 } | |
| 492 // If the page number is out of bounds, reset to the first tab. | |
| 493 if (page < 0 || page >= gtk_notebook_get_n_pages(GTK_NOTEBOOK(notebook_))) | |
| 494 page = CERT_MANAGER_PAGE_USER; | |
| 495 | |
| 496 gtk_notebook_set_current_page(GTK_NOTEBOOK(notebook_), page); | |
| 497 } | |
| 498 | |
| 499 } // namespace | |
| 500 | |
| 501 namespace certificate_manager_util { | |
| 502 | |
| 503 void RegisterUserPrefs(PrefService* prefs) { | |
| 504 prefs->RegisterIntegerPref(prefs::kCertificateManagerWindowLastTabIndex, 0); | |
| 505 } | |
| 506 | |
| 507 } // namespace certificate_manager_util | |
| 508 | |
| 509 void ShowCertificateManager(gfx::NativeWindow parent, Profile* profile, | |
| 510 CertificateManagerPage page) { | |
| 511 base::EnsureNSSInit(); | |
| 512 CertificateManager* manager = new CertificateManager(parent, profile); | |
| 513 manager->ShowCertificatePage(page); | |
| 514 } | |
| OLD | NEW |