| 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 | 
|---|