Home | History | Annotate | Download | only in website_settings
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "chrome/browser/ui/views/website_settings/website_settings_popup_view.h"
      6 
      7 #include <algorithm>
      8 
      9 #include "base/strings/string_number_conversions.h"
     10 #include "base/strings/utf_string_conversions.h"
     11 #include "chrome/browser/certificate_viewer.h"
     12 #include "chrome/browser/infobars/infobar_service.h"
     13 #include "chrome/browser/profiles/profile.h"
     14 #include "chrome/browser/ui/browser.h"
     15 #include "chrome/browser/ui/browser_dialogs.h"
     16 #include "chrome/browser/ui/views/collected_cookies_views.h"
     17 #include "chrome/browser/ui/views/website_settings/permission_selector_view.h"
     18 #include "chrome/browser/ui/website_settings/website_settings.h"
     19 #include "chrome/browser/ui/website_settings/website_settings_utils.h"
     20 #include "chrome/common/url_constants.h"
     21 #include "chrome/grit/chromium_strings.h"
     22 #include "chrome/grit/generated_resources.h"
     23 #include "components/content_settings/core/common/content_settings_types.h"
     24 #include "content/public/browser/browser_thread.h"
     25 #include "content/public/browser/cert_store.h"
     26 #include "content/public/browser/user_metrics.h"
     27 #include "grit/theme_resources.h"
     28 #include "ui/base/l10n/l10n_util.h"
     29 #include "ui/base/models/simple_menu_model.h"
     30 #include "ui/base/resource/resource_bundle.h"
     31 #include "ui/gfx/canvas.h"
     32 #include "ui/gfx/font_list.h"
     33 #include "ui/gfx/image/image.h"
     34 #include "ui/gfx/insets.h"
     35 #include "ui/resources/grit/ui_resources.h"
     36 #include "ui/views/controls/button/image_button.h"
     37 #include "ui/views/controls/button/menu_button.h"
     38 #include "ui/views/controls/button/menu_button_listener.h"
     39 #include "ui/views/controls/image_view.h"
     40 #include "ui/views/controls/label.h"
     41 #include "ui/views/controls/link.h"
     42 #include "ui/views/controls/menu/menu_model_adapter.h"
     43 #include "ui/views/controls/menu/menu_runner.h"
     44 #include "ui/views/controls/separator.h"
     45 #include "ui/views/controls/tabbed_pane/tabbed_pane.h"
     46 #include "ui/views/layout/box_layout.h"
     47 #include "ui/views/layout/grid_layout.h"
     48 #include "ui/views/layout/layout_manager.h"
     49 #include "ui/views/view.h"
     50 #include "ui/views/widget/widget.h"
     51 #include "url/gurl.h"
     52 
     53 namespace {
     54 
     55 // NOTE(jdonnelly): This use of this process-wide variable assumes that there's
     56 // never more than one website settings popup shown and that it's associated
     57 // with the current window. If this assumption fails in the future, we'll need
     58 // to return a weak pointer from ShowPopup so callers can associate it with the
     59 // current window (or other context) and check if the popup they care about is
     60 // showing.
     61 bool is_popup_showing = false;
     62 
     63 // Padding values for sections on the connection tab.
     64 const int kConnectionSectionPaddingBottom = 16;
     65 const int kConnectionSectionPaddingLeft = 18;
     66 const int kConnectionSectionPaddingTop = 16;
     67 const int kConnectionSectionPaddingRight = 18;
     68 
     69 // The text color that is used for the site identity status text, if the site's
     70 // identity was sucessfully verified.
     71 const SkColor kIdentityVerifiedTextColor = 0xFF298a27;
     72 
     73 // Left icon margin.
     74 const int kIconMarginLeft = 6;
     75 
     76 // Margin and padding values for the |PopupHeaderView|.
     77 const int kHeaderMarginBottom = 10;
     78 const int kHeaderPaddingBottom = 12;
     79 const int kHeaderPaddingLeft = 18;
     80 const int kHeaderPaddingRight = 8;
     81 const int kHeaderPaddingTop = 12;
     82 
     83 // Spacing between the site identity label and the site identity status text in
     84 // the popup header.
     85 const int kHeaderRowSpacing = 4;
     86 
     87 // To make the bubble's arrow point directly at the location icon rather than at
     88 // the Omnibox's edge, inset the bubble's anchor rect by this amount of pixels.
     89 const int kLocationIconVerticalMargin = 5;
     90 
     91 // The max possible width of the popup.
     92 const int kMaxPopupWidth = 500;
     93 
     94 // The margins between the popup border and the popup content.
     95 const int kPopupMarginTop = 4;
     96 const int kPopupMarginLeft = 0;
     97 const int kPopupMarginBottom = 10;
     98 const int kPopupMarginRight = 0;
     99 
    100 // Padding values for sections on the permissions tab.
    101 const int kPermissionsSectionContentMinWidth = 300;
    102 const int kPermissionsSectionPaddingBottom = 6;
    103 const int kPermissionsSectionPaddingLeft = 18;
    104 const int kPermissionsSectionPaddingTop = 16;
    105 
    106 // Space between the headline and the content of a section on the permissions
    107 // tab.
    108 const int kPermissionsSectionHeadlineMarginBottom = 10;
    109 // The content of the "Permissions" section and the "Cookies and Site Data"
    110 // section is structured in individual rows. |kPermissionsSectionRowSpacing|
    111 // is the space between these rows.
    112 const int kPermissionsSectionRowSpacing = 2;
    113 
    114 const int kSiteDataIconColumnWidth = 20;
    115 const int kSiteDataSectionRowSpacing = 11;
    116 
    117 }  // namespace
    118 
    119 // |PopupHeaderView| is the UI element (view) that represents the header of the
    120 // |WebsiteSettingsPopupView|. The header shows the status of the site's
    121 // identity check and the name of the site's identity.
    122 class PopupHeaderView : public views::View {
    123  public:
    124   explicit PopupHeaderView(views::ButtonListener* close_button_listener);
    125   virtual ~PopupHeaderView();
    126 
    127   // Sets the name of the site's identity.
    128   void SetIdentityName(const base::string16& name);
    129 
    130   // Sets the |status_text| for the identity check of this site and the
    131   // |text_color|.
    132   void SetIdentityStatus(const base::string16& status_text, SkColor text_color);
    133 
    134  private:
    135   // The label that displays the name of the site's identity.
    136   views::Label* name_;
    137   // The label that displays the status of the identity check for this site.
    138   views::Label* status_;
    139 
    140   DISALLOW_COPY_AND_ASSIGN(PopupHeaderView);
    141 };
    142 
    143 // Website Settings are not supported for internal Chrome pages. Instead of the
    144 // |WebsiteSettingsPopupView|, the |InternalPageInfoPopupView| is
    145 // displayed.
    146 class InternalPageInfoPopupView : public views::BubbleDelegateView {
    147  public:
    148   explicit InternalPageInfoPopupView(views::View* anchor_view);
    149   virtual ~InternalPageInfoPopupView();
    150 
    151   // views::BubbleDelegateView:
    152   virtual void OnWidgetDestroying(views::Widget* widget) OVERRIDE;
    153 
    154  private:
    155   DISALLOW_COPY_AND_ASSIGN(InternalPageInfoPopupView);
    156 };
    157 
    158 ////////////////////////////////////////////////////////////////////////////////
    159 // Popup Header
    160 ////////////////////////////////////////////////////////////////////////////////
    161 
    162 PopupHeaderView::PopupHeaderView(views::ButtonListener* close_button_listener)
    163     : name_(NULL), status_(NULL) {
    164   views::GridLayout* layout = new views::GridLayout(this);
    165   SetLayoutManager(layout);
    166 
    167   const int label_column = 0;
    168   views::ColumnSet* column_set = layout->AddColumnSet(label_column);
    169   column_set->AddPaddingColumn(0, kHeaderPaddingLeft);
    170   column_set->AddColumn(views::GridLayout::FILL,
    171                         views::GridLayout::FILL,
    172                         1,
    173                         views::GridLayout::USE_PREF,
    174                         0,
    175                         0);
    176   column_set->AddPaddingColumn(1, 0);
    177   column_set->AddColumn(views::GridLayout::FILL,
    178                         views::GridLayout::FILL,
    179                         1,
    180                         views::GridLayout::USE_PREF,
    181                         0,
    182                         0);
    183   column_set->AddPaddingColumn(0, kHeaderPaddingRight);
    184 
    185   layout->AddPaddingRow(0, kHeaderPaddingTop);
    186 
    187   layout->StartRow(0, label_column);
    188   ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
    189   name_ = new views::Label(
    190       base::string16(), rb.GetFontList(ui::ResourceBundle::BoldFont));
    191   layout->AddView(name_, 1, 1, views::GridLayout::LEADING,
    192                   views::GridLayout::TRAILING);
    193   views::ImageButton* close_button =
    194       new views::ImageButton(close_button_listener);
    195   close_button->SetImage(views::CustomButton::STATE_NORMAL,
    196                          rb.GetImageNamed(IDR_CLOSE_2).ToImageSkia());
    197   close_button->SetImage(views::CustomButton::STATE_HOVERED,
    198                          rb.GetImageNamed(IDR_CLOSE_2_H).ToImageSkia());
    199   close_button->SetImage(views::CustomButton::STATE_PRESSED,
    200                          rb.GetImageNamed(IDR_CLOSE_2_P).ToImageSkia());
    201   layout->AddView(close_button, 1, 1, views::GridLayout::TRAILING,
    202                   views::GridLayout::LEADING);
    203 
    204   layout->AddPaddingRow(0, kHeaderRowSpacing);
    205 
    206   layout->StartRow(0, label_column);
    207   status_ = new views::Label(base::string16());
    208   layout->AddView(status_,
    209                   1,
    210                   1,
    211                   views::GridLayout::LEADING,
    212                   views::GridLayout::CENTER);
    213 
    214   layout->AddPaddingRow(0, kHeaderPaddingBottom);
    215 }
    216 
    217 PopupHeaderView::~PopupHeaderView() {
    218 }
    219 
    220 void PopupHeaderView::SetIdentityName(const base::string16& name) {
    221   name_->SetText(name);
    222 }
    223 
    224 void PopupHeaderView::SetIdentityStatus(const base::string16& status,
    225                                         SkColor text_color) {
    226   status_->SetText(status);
    227   status_->SetEnabledColor(text_color);
    228 }
    229 
    230 ////////////////////////////////////////////////////////////////////////////////
    231 // InternalPageInfoPopupView
    232 ////////////////////////////////////////////////////////////////////////////////
    233 
    234 InternalPageInfoPopupView::InternalPageInfoPopupView(views::View* anchor_view)
    235     : BubbleDelegateView(anchor_view, views::BubbleBorder::TOP_LEFT) {
    236   // Compensate for built-in vertical padding in the anchor view's image.
    237   set_anchor_view_insets(gfx::Insets(kLocationIconVerticalMargin, 0,
    238                                      kLocationIconVerticalMargin, 0));
    239 
    240   const int kSpacing = 4;
    241   SetLayoutManager(new views::BoxLayout(views::BoxLayout::kHorizontal, kSpacing,
    242                                         kSpacing, kSpacing));
    243   views::ImageView* icon_view = new views::ImageView();
    244   ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
    245   icon_view->SetImage(rb.GetImageSkiaNamed(IDR_PRODUCT_LOGO_26));
    246   AddChildView(icon_view);
    247 
    248   views::Label* label =
    249       new views::Label(l10n_util::GetStringUTF16(IDS_PAGE_INFO_INTERNAL_PAGE));
    250   label->SetMultiLine(true);
    251   label->SetAllowCharacterBreak(true);
    252   label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
    253   AddChildView(label);
    254 
    255   views::BubbleDelegateView::CreateBubble(this)->Show();
    256   SizeToContents();
    257 }
    258 
    259 InternalPageInfoPopupView::~InternalPageInfoPopupView() {
    260 }
    261 
    262 void InternalPageInfoPopupView::OnWidgetDestroying(views::Widget* widget) {
    263   is_popup_showing = false;
    264 }
    265 
    266 ////////////////////////////////////////////////////////////////////////////////
    267 // WebsiteSettingsPopupView
    268 ////////////////////////////////////////////////////////////////////////////////
    269 
    270 WebsiteSettingsPopupView::~WebsiteSettingsPopupView() {
    271 }
    272 
    273 // static
    274 void WebsiteSettingsPopupView::ShowPopup(views::View* anchor_view,
    275                                          Profile* profile,
    276                                          content::WebContents* web_contents,
    277                                          const GURL& url,
    278                                          const content::SSLStatus& ssl,
    279                                          Browser* browser) {
    280   is_popup_showing = true;
    281   if (InternalChromePage(url)) {
    282     new InternalPageInfoPopupView(anchor_view);
    283   } else {
    284     new WebsiteSettingsPopupView(anchor_view, profile, web_contents, url, ssl,
    285                                  browser);
    286   }
    287 }
    288 
    289 // static
    290 bool WebsiteSettingsPopupView::IsPopupShowing() {
    291   return is_popup_showing;
    292 }
    293 
    294 WebsiteSettingsPopupView::WebsiteSettingsPopupView(
    295     views::View* anchor_view,
    296     Profile* profile,
    297     content::WebContents* web_contents,
    298     const GURL& url,
    299     const content::SSLStatus& ssl,
    300     Browser* browser)
    301     : BubbleDelegateView(anchor_view, views::BubbleBorder::TOP_LEFT),
    302       web_contents_(web_contents),
    303       browser_(browser),
    304       header_(NULL),
    305       tabbed_pane_(NULL),
    306       site_data_content_(NULL),
    307       cookie_dialog_link_(NULL),
    308       permissions_content_(NULL),
    309       connection_tab_(NULL),
    310       identity_info_content_(NULL),
    311       certificate_dialog_link_(NULL),
    312       signed_certificate_timestamps_link_(NULL),
    313       reset_decisions_button_(NULL),
    314       cert_id_(0),
    315       help_center_link_(NULL),
    316       connection_info_content_(NULL),
    317       page_info_content_(NULL),
    318       weak_factory_(this) {
    319   // Compensate for built-in vertical padding in the anchor view's image.
    320   set_anchor_view_insets(gfx::Insets(kLocationIconVerticalMargin, 0,
    321                                      kLocationIconVerticalMargin, 0));
    322 
    323   views::GridLayout* layout = new views::GridLayout(this);
    324   SetLayoutManager(layout);
    325   const int content_column = 0;
    326   views::ColumnSet* column_set = layout->AddColumnSet(content_column);
    327   column_set->AddColumn(views::GridLayout::FILL,
    328                         views::GridLayout::FILL,
    329                         1,
    330                         views::GridLayout::USE_PREF,
    331                         0,
    332                         0);
    333 
    334   header_ = new PopupHeaderView(this);
    335   layout->StartRow(1, content_column);
    336   layout->AddView(header_);
    337 
    338   layout->AddPaddingRow(1, kHeaderMarginBottom);
    339   tabbed_pane_ = new views::TabbedPane();
    340   layout->StartRow(1, content_column);
    341   layout->AddView(tabbed_pane_);
    342   // Tabs must be added after the tabbed_pane_ was added to the views
    343   // hierachy.  Adding the |tabbed_pane_| to the views hierachy triggers the
    344   // initialization of the native tab UI element. If the native tab UI
    345   // element is not initalized adding a tab will result in a NULL pointer
    346   // exception.
    347   tabbed_pane_->AddTabAtIndex(
    348       TAB_ID_PERMISSIONS,
    349       l10n_util::GetStringUTF16(IDS_WEBSITE_SETTINGS_TAB_LABEL_PERMISSIONS),
    350       CreatePermissionsTab());
    351   connection_tab_ = CreateConnectionTab();
    352   tabbed_pane_->AddTabAtIndex(
    353       TAB_ID_CONNECTION,
    354       l10n_util::GetStringUTF16(IDS_WEBSITE_SETTINGS_TAB_LABEL_CONNECTION),
    355       connection_tab_);
    356   DCHECK_EQ(tabbed_pane_->GetTabCount(), NUM_TAB_IDS);
    357   tabbed_pane_->set_listener(this);
    358 
    359   set_margins(gfx::Insets(kPopupMarginTop, kPopupMarginLeft,
    360                           kPopupMarginBottom, kPopupMarginRight));
    361 
    362   views::BubbleDelegateView::CreateBubble(this)->Show();
    363   SizeToContents();
    364 
    365   presenter_.reset(new WebsiteSettings(
    366       this, profile,
    367       TabSpecificContentSettings::FromWebContents(web_contents),
    368       InfoBarService::FromWebContents(web_contents), url, ssl,
    369       content::CertStore::GetInstance()));
    370 }
    371 
    372 void WebsiteSettingsPopupView::OnPermissionChanged(
    373     const WebsiteSettingsUI::PermissionInfo& permission) {
    374   presenter_->OnSitePermissionChanged(permission.type, permission.setting);
    375 }
    376 
    377 void WebsiteSettingsPopupView::OnWidgetDestroying(views::Widget* widget) {
    378   is_popup_showing = false;
    379   presenter_->OnUIClosing();
    380 }
    381 
    382 void WebsiteSettingsPopupView::ButtonPressed(views::Button* button,
    383                                              const ui::Event& event) {
    384   if (button == reset_decisions_button_)
    385     presenter_->OnRevokeSSLErrorBypassButtonPressed();
    386   GetWidget()->Close();
    387 }
    388 
    389 void WebsiteSettingsPopupView::LinkClicked(views::Link* source,
    390                                            int event_flags) {
    391   if (source == cookie_dialog_link_) {
    392     // Count how often the Collected Cookies dialog is opened.
    393     content::RecordAction(
    394         base::UserMetricsAction("WebsiteSettings_CookiesDialogOpened"));
    395     new CollectedCookiesViews(web_contents_);
    396   } else if (source == certificate_dialog_link_) {
    397     gfx::NativeWindow parent = GetAnchorView() ?
    398         GetAnchorView()->GetWidget()->GetNativeWindow() : NULL;
    399     ShowCertificateViewerByID(web_contents_, parent, cert_id_);
    400   } else if (source == signed_certificate_timestamps_link_) {
    401     chrome::ShowSignedCertificateTimestampsViewer(
    402         web_contents_, signed_certificate_timestamp_ids_);
    403   } else if (source == help_center_link_) {
    404     browser_->OpenURL(
    405         content::OpenURLParams(GURL(chrome::kPageInfoHelpCenterURL),
    406                                content::Referrer(),
    407                                NEW_FOREGROUND_TAB,
    408                                ui::PAGE_TRANSITION_LINK,
    409                                false));
    410   }
    411 }
    412 
    413 void WebsiteSettingsPopupView::TabSelectedAt(int index) {
    414   tabbed_pane_->GetSelectedTab()->Layout();
    415   SizeToContents();
    416 }
    417 
    418 gfx::Size WebsiteSettingsPopupView::GetPreferredSize() const {
    419   if (header_ == NULL && tabbed_pane_ == NULL)
    420     return views::View::GetPreferredSize();
    421 
    422   int height = 0;
    423   if (header_)
    424     height += header_->GetPreferredSize().height();
    425   if (tabbed_pane_)
    426     height += tabbed_pane_->GetPreferredSize().height();
    427 
    428   int width = kPermissionsSectionContentMinWidth;
    429   if (site_data_content_)
    430     width = std::max(width, site_data_content_->GetPreferredSize().width());
    431   if (permissions_content_)
    432     width = std::max(width, permissions_content_->GetPreferredSize().width());
    433   width += kPermissionsSectionPaddingLeft;
    434   width = std::min(width, kMaxPopupWidth);
    435 
    436   return gfx::Size(width, height);
    437 }
    438 
    439 void WebsiteSettingsPopupView::SetCookieInfo(
    440     const CookieInfoList& cookie_info_list) {
    441   site_data_content_->RemoveAllChildViews(true);
    442 
    443   views::GridLayout* layout = new views::GridLayout(site_data_content_);
    444   site_data_content_->SetLayoutManager(layout);
    445 
    446   const int site_data_content_column = 0;
    447   views::ColumnSet* column_set =
    448       layout->AddColumnSet(site_data_content_column);
    449   column_set->AddColumn(views::GridLayout::FILL,
    450                         views::GridLayout::FILL,
    451                         1,
    452                         views::GridLayout::FIXED,
    453                         kSiteDataIconColumnWidth,
    454                         0);
    455   column_set->AddPaddingColumn(0, kIconMarginLeft);
    456   column_set->AddColumn(views::GridLayout::FILL,
    457                         views::GridLayout::FILL,
    458                         1,
    459                         views::GridLayout::USE_PREF,
    460                         0,
    461                         0);
    462 
    463   layout->AddPaddingRow(1, 5);
    464   for (CookieInfoList::const_iterator i(cookie_info_list.begin());
    465        i != cookie_info_list.end();
    466        ++i) {
    467     base::string16 label_text = l10n_util::GetStringFUTF16(
    468         IDS_WEBSITE_SETTINGS_SITE_DATA_STATS_LINE,
    469         base::UTF8ToUTF16(i->cookie_source),
    470         base::IntToString16(i->allowed),
    471         base::IntToString16(i->blocked));
    472     if (i != cookie_info_list.begin())
    473       layout->AddPaddingRow(1, kSiteDataSectionRowSpacing);
    474     layout->StartRow(1, site_data_content_column);
    475     WebsiteSettingsUI::PermissionInfo info;
    476     info.type = CONTENT_SETTINGS_TYPE_COOKIES;
    477     info.setting = CONTENT_SETTING_ALLOW;
    478     views::ImageView* icon = new views::ImageView();
    479     const gfx::Image& image = WebsiteSettingsUI::GetPermissionIcon(info);
    480     icon->SetImage(image.ToImageSkia());
    481     layout->AddView(icon, 1, 1, views::GridLayout::CENTER,
    482                     views::GridLayout::CENTER);
    483     layout->AddView(new views::Label(label_text), 1, 1,
    484                     views::GridLayout::LEADING, views::GridLayout::CENTER);
    485   }
    486   layout->AddPaddingRow(1, 6);
    487 
    488   layout->Layout(site_data_content_);
    489   SizeToContents();
    490 }
    491 
    492 void WebsiteSettingsPopupView::SetPermissionInfo(
    493     const PermissionInfoList& permission_info_list) {
    494   permissions_content_->RemoveAllChildViews(true);
    495 
    496   views::GridLayout* layout =
    497       new views::GridLayout(permissions_content_);
    498   permissions_content_->SetLayoutManager(layout);
    499   const int content_column = 0;
    500   views::ColumnSet* column_set =
    501       layout->AddColumnSet(content_column);
    502   column_set->AddColumn(views::GridLayout::FILL,
    503                         views::GridLayout::FILL,
    504                         1,
    505                         views::GridLayout::USE_PREF,
    506                         0,
    507                         0);
    508   for (PermissionInfoList::const_iterator permission =
    509            permission_info_list.begin();
    510        permission != permission_info_list.end();
    511        ++permission) {
    512     layout->StartRow(1, content_column);
    513     PermissionSelectorView* selector = new PermissionSelectorView(
    514         web_contents_ ? web_contents_->GetURL() : GURL::EmptyGURL(),
    515         *permission);
    516     selector->AddObserver(this);
    517     layout->AddView(selector,
    518                     1,
    519                     1,
    520                     views::GridLayout::LEADING,
    521                     views::GridLayout::CENTER);
    522     layout->AddPaddingRow(1, kPermissionsSectionRowSpacing);
    523   }
    524 
    525   SizeToContents();
    526 }
    527 
    528 void WebsiteSettingsPopupView::SetIdentityInfo(
    529     const IdentityInfo& identity_info) {
    530   base::string16 identity_status_text;
    531   SkColor text_color = SK_ColorBLACK;
    532   switch (identity_info.identity_status) {
    533     case WebsiteSettings::SITE_IDENTITY_STATUS_CERT:
    534     case WebsiteSettings::SITE_IDENTITY_STATUS_EV_CERT:
    535       identity_status_text =
    536           l10n_util::GetStringUTF16(IDS_WEBSITE_SETTINGS_IDENTITY_VERIFIED);
    537       text_color = kIdentityVerifiedTextColor;
    538       break;
    539     case WebsiteSettings::SITE_IDENTITY_STATUS_ADMIN_PROVIDED_CERT:
    540       identity_status_text =
    541           l10n_util::GetStringUTF16(IDS_CERT_POLICY_PROVIDED_CERT_HEADER);
    542       break;
    543     default:
    544       identity_status_text =
    545          l10n_util::GetStringUTF16(IDS_WEBSITE_SETTINGS_IDENTITY_NOT_VERIFIED);
    546       break;
    547   }
    548   header_->SetIdentityName(base::UTF8ToUTF16(identity_info.site_identity));
    549   header_->SetIdentityStatus(identity_status_text, text_color);
    550 
    551   // The headline and the certificate dialog link of the site's identity
    552   // section is only displayed if the site's identity was verified. If the
    553   // site's identity was verified, then the headline contains the organization
    554   // name from the provided certificate. If the organization name is not
    555   // available than the hostname of the site is used instead.
    556   base::string16 headline;
    557   if (identity_info.cert_id) {
    558     cert_id_ = identity_info.cert_id;
    559     signed_certificate_timestamp_ids_.assign(
    560         identity_info.signed_certificate_timestamp_ids.begin(),
    561         identity_info.signed_certificate_timestamp_ids.end());
    562 
    563     certificate_dialog_link_ = new views::Link(
    564         l10n_util::GetStringUTF16(IDS_PAGEINFO_CERT_INFO_BUTTON));
    565     certificate_dialog_link_->set_listener(this);
    566 
    567     if (!signed_certificate_timestamp_ids_.empty()) {
    568       signed_certificate_timestamps_link_ =
    569           new views::Link(l10n_util::GetStringUTF16(
    570               IDS_PAGEINFO_CERT_TRANSPARENCY_INFO_BUTTON));
    571       signed_certificate_timestamps_link_->set_listener(this);
    572     }
    573 
    574     if (identity_info.show_ssl_decision_revoke_button) {
    575       reset_decisions_button_ = new views::LabelButton(
    576           this,
    577           l10n_util::GetStringUTF16(
    578               IDS_PAGEINFO_RESET_INVALID_CERTIFICATE_DECISIONS_BUTTON));
    579       reset_decisions_button_->SetStyle(views::Button::STYLE_BUTTON);
    580     }
    581 
    582     headline = base::UTF8ToUTF16(identity_info.site_identity);
    583   }
    584   ResetConnectionSection(
    585       identity_info_content_,
    586       WebsiteSettingsUI::GetIdentityIcon(identity_info.identity_status),
    587       base::string16(),  // The identity section has no headline.
    588       base::UTF8ToUTF16(identity_info.identity_status_description),
    589       certificate_dialog_link_,
    590       signed_certificate_timestamps_link_,
    591       reset_decisions_button_);
    592 
    593   ResetConnectionSection(
    594       connection_info_content_,
    595       WebsiteSettingsUI::GetConnectionIcon(identity_info.connection_status),
    596       base::string16(),  // The connection section has no headline.
    597       base::UTF8ToUTF16(identity_info.connection_status_description),
    598       NULL,
    599       NULL,
    600       NULL);
    601 
    602   connection_tab_->InvalidateLayout();
    603   Layout();
    604   SizeToContents();
    605 }
    606 
    607 void WebsiteSettingsPopupView::SetFirstVisit(
    608     const base::string16& first_visit) {
    609   ResetConnectionSection(
    610       page_info_content_,
    611       WebsiteSettingsUI::GetFirstVisitIcon(first_visit),
    612       l10n_util::GetStringUTF16(IDS_PAGE_INFO_SITE_INFO_TITLE),
    613       first_visit,
    614       NULL,
    615       NULL,
    616       NULL);
    617   connection_tab_->InvalidateLayout();
    618   Layout();
    619   SizeToContents();
    620 }
    621 
    622 void WebsiteSettingsPopupView::SetSelectedTab(TabId tab_id) {
    623   tabbed_pane_->SelectTabAt(tab_id);
    624 }
    625 
    626 views::View* WebsiteSettingsPopupView::CreatePermissionsTab() {
    627   views::View* pane = new views::View();
    628   pane->SetLayoutManager(
    629       new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 1));
    630   // Add cookies and site data section.
    631   cookie_dialog_link_ = new views::Link(
    632       l10n_util::GetStringUTF16(IDS_WEBSITE_SETTINGS_SHOW_SITE_DATA));
    633   cookie_dialog_link_->set_listener(this);
    634   site_data_content_ = new views::View();
    635   views::View* site_data_section =
    636       CreateSection(l10n_util::GetStringUTF16(
    637                         IDS_WEBSITE_SETTINGS_TITLE_SITE_DATA),
    638                     site_data_content_,
    639                     cookie_dialog_link_);
    640   pane->AddChildView(site_data_section);
    641   // Add permissions section.
    642   permissions_content_ = new views::View();
    643   views::View* permissions_section =
    644       CreateSection(l10n_util::GetStringUTF16(
    645                         IDS_WEBSITE_SETTINGS_TITLE_SITE_PERMISSIONS),
    646                     permissions_content_,
    647                     NULL);
    648   pane->AddChildView(permissions_section);
    649   return pane;
    650 }
    651 
    652 views::View* WebsiteSettingsPopupView::CreateConnectionTab() {
    653   views::View* pane = new views::View();
    654   pane->SetLayoutManager(
    655       new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 1));
    656   // Add site identity section.
    657   identity_info_content_ = new views::View();
    658   pane->AddChildView(identity_info_content_);
    659 
    660   // Add connection section.
    661   pane->AddChildView(new views::Separator(views::Separator::HORIZONTAL));
    662   connection_info_content_ = new views::View();
    663   pane->AddChildView(connection_info_content_);
    664 
    665   // Add page info section.
    666   pane->AddChildView(new views::Separator(views::Separator::HORIZONTAL));
    667   page_info_content_ = new views::View();
    668   pane->AddChildView(page_info_content_);
    669 
    670   // Add help center link.
    671   pane->AddChildView(new views::Separator(views::Separator::HORIZONTAL));
    672   help_center_link_ = new views::Link(
    673       l10n_util::GetStringUTF16(IDS_PAGE_INFO_HELP_CENTER_LINK));
    674   help_center_link_->set_listener(this);
    675   views::View* link_section = new views::View();
    676   const int kLinkMarginTop = 4;
    677   link_section->SetLayoutManager(
    678       new views::BoxLayout(views::BoxLayout::kHorizontal,
    679                            kConnectionSectionPaddingLeft,
    680                            kLinkMarginTop,
    681                            0));
    682   link_section->AddChildView(help_center_link_);
    683   pane->AddChildView(link_section);
    684   return pane;
    685 }
    686 
    687 views::View* WebsiteSettingsPopupView::CreateSection(
    688     const base::string16& headline_text,
    689     views::View* content,
    690     views::Link* link) {
    691   views::View* container = new views::View();
    692   views::GridLayout* layout = new views::GridLayout(container);
    693   container->SetLayoutManager(layout);
    694   const int content_column = 0;
    695   views::ColumnSet* column_set = layout->AddColumnSet(content_column);
    696   column_set->AddPaddingColumn(0, kPermissionsSectionPaddingLeft);
    697   column_set->AddColumn(views::GridLayout::FILL,
    698                         views::GridLayout::FILL,
    699                         1,
    700                         views::GridLayout::USE_PREF,
    701                         0,
    702                         0);
    703 
    704   layout->AddPaddingRow(1, kPermissionsSectionPaddingTop);
    705   layout->StartRow(1, content_column);
    706   ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
    707   views::Label* headline = new views::Label(
    708       headline_text, rb.GetFontList(ui::ResourceBundle::BoldFont));
    709   layout->AddView(headline, 1, 1, views::GridLayout::LEADING,
    710                   views::GridLayout::CENTER);
    711 
    712   layout->AddPaddingRow(1, kPermissionsSectionHeadlineMarginBottom);
    713   layout->StartRow(1, content_column);
    714   layout->AddView(content, 1, 1, views::GridLayout::LEADING,
    715                   views::GridLayout::CENTER);
    716 
    717   if (link) {
    718     layout->AddPaddingRow(1, 4);
    719     layout->StartRow(1, content_column);
    720     layout->AddView(link, 1, 1, views::GridLayout::LEADING,
    721                     views::GridLayout::CENTER);
    722   }
    723 
    724   layout->AddPaddingRow(1, kPermissionsSectionPaddingBottom);
    725   return container;
    726 }
    727 
    728 void WebsiteSettingsPopupView::ResetConnectionSection(
    729     views::View* section_container,
    730     const gfx::Image& icon,
    731     const base::string16& headline,
    732     const base::string16& text,
    733     views::Link* link,
    734     views::Link* secondary_link,
    735     views::LabelButton* reset_decisions_button) {
    736   section_container->RemoveAllChildViews(true);
    737 
    738   views::GridLayout* layout = new views::GridLayout(section_container);
    739   section_container->SetLayoutManager(layout);
    740   views::ColumnSet* column_set = layout->AddColumnSet(0);
    741   column_set->AddPaddingColumn(0, kConnectionSectionPaddingLeft);
    742   column_set->AddColumn(views::GridLayout::LEADING,
    743                         views::GridLayout::LEADING,
    744                         0,
    745                         views::GridLayout::USE_PREF,
    746                         0,
    747                         0);
    748   column_set->AddPaddingColumn(0, kIconMarginLeft);
    749   column_set->AddColumn(views::GridLayout::FILL,
    750                         views::GridLayout::FILL,
    751                         1,
    752                         views::GridLayout::USE_PREF,
    753                         0,
    754                         0);
    755   column_set->AddPaddingColumn(0, kConnectionSectionPaddingRight);
    756 
    757 
    758   layout->AddPaddingRow(0, kConnectionSectionPaddingTop);
    759   layout->StartRow(1, 0);
    760 
    761   // Add status icon.
    762   views::ImageView* icon_view = new views::ImageView();
    763   icon_view->SetImage(*icon.ToImageSkia());
    764   layout->AddView(icon_view, 1, 1, views::GridLayout::LEADING,
    765                   views::GridLayout::LEADING);
    766 
    767   // Add section content.
    768   views::View* content_pane = new views::View();
    769   views::GridLayout* content_layout = new views::GridLayout(content_pane);
    770   content_pane->SetLayoutManager(content_layout);
    771   views::ColumnSet* content_column_set = content_layout->AddColumnSet(0);
    772   content_column_set->AddColumn(views::GridLayout::LEADING,
    773                                 views::GridLayout::LEADING,
    774                                 1,
    775                                 views::GridLayout::USE_PREF,
    776                                 0,
    777                                 0);
    778   if (!headline.empty()) {
    779     ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
    780     views::Label* headline_label = new views::Label(
    781         headline, rb.GetFontList(ui::ResourceBundle::BoldFont));
    782     headline_label->SetMultiLine(true);
    783     headline_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
    784     // Allow linebreaking in the middle of words if necessary, so that extremely
    785     // long hostnames (longer than one line) will still be completely shown.
    786     headline_label->SetAllowCharacterBreak(true);
    787     content_layout->StartRow(1, 0);
    788     content_layout->AddView(headline_label);
    789   }
    790 
    791   views::Label* description_label = new views::Label(text);
    792   description_label->SetMultiLine(true);
    793   description_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
    794   description_label->SetAllowCharacterBreak(true);
    795   content_layout->StartRow(1, 0);
    796   content_layout->AddView(description_label);
    797 
    798   if (link) {
    799     content_layout->StartRow(1, 0);
    800     content_layout->AddView(link);
    801   }
    802 
    803   if (secondary_link) {
    804     content_layout->StartRow(1, 0);
    805     content_layout->AddView(secondary_link);
    806   }
    807 
    808   if (reset_decisions_button) {
    809     content_layout->StartRow(1, 0);
    810     content_layout->AddView(reset_decisions_button);
    811   }
    812 
    813   layout->AddView(content_pane, 1, 1, views::GridLayout::LEADING,
    814                   views::GridLayout::LEADING);
    815   layout->AddPaddingRow(0, kConnectionSectionPaddingBottom);
    816 }
    817