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