website_settings_popup_view.cc revision eb525c5499e34cc9c4b825d6d9e75bb07cc06ace
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 "googleurl/src/gurl.h"
22#include "grit/chromium_strings.h"
23#include "grit/generated_resources.h"
24#include "grit/theme_resources.h"
25#include "grit/ui_resources.h"
26#include "ui/base/l10n/l10n_util.h"
27#include "ui/base/models/simple_menu_model.h"
28#include "ui/base/resource/resource_bundle.h"
29#include "ui/gfx/canvas.h"
30#include "ui/gfx/font.h"
31#include "ui/gfx/image/image.h"
32#include "ui/gfx/insets.h"
33#include "ui/views/controls/button/image_button.h"
34#include "ui/views/controls/button/menu_button.h"
35#include "ui/views/controls/button/menu_button_listener.h"
36#include "ui/views/controls/image_view.h"
37#include "ui/views/controls/label.h"
38#include "ui/views/controls/link.h"
39#include "ui/views/controls/menu/menu_model_adapter.h"
40#include "ui/views/controls/menu/menu_runner.h"
41#include "ui/views/controls/separator.h"
42#include "ui/views/controls/tabbed_pane/tabbed_pane.h"
43#include "ui/views/layout/box_layout.h"
44#include "ui/views/layout/grid_layout.h"
45#include "ui/views/layout/layout_manager.h"
46#include "ui/views/view.h"
47#include "ui/views/widget/widget.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
271WebsiteSettingsPopupView::WebsiteSettingsPopupView(
272    views::View* anchor_view,
273    Profile* profile,
274    content::WebContents* web_contents,
275    const GURL& url,
276    const content::SSLStatus& ssl,
277    Browser* browser)
278    : BubbleDelegateView(anchor_view, views::BubbleBorder::TOP_LEFT),
279      web_contents_(web_contents),
280      browser_(browser),
281      header_(NULL),
282      tabbed_pane_(NULL),
283      site_data_content_(NULL),
284      cookie_dialog_link_(NULL),
285      permissions_content_(NULL),
286      connection_tab_(NULL),
287      identity_info_content_(NULL),
288      certificate_dialog_link_(NULL),
289      cert_id_(0),
290      help_center_link_(NULL),
291      connection_info_content_(NULL),
292      page_info_content_(NULL) {
293  // Compensate for built-in vertical padding in the anchor view's image.
294  set_anchor_view_insets(gfx::Insets(kLocationIconVerticalMargin, 0,
295                                     kLocationIconVerticalMargin, 0));
296
297  views::GridLayout* layout = new views::GridLayout(this);
298  SetLayoutManager(layout);
299  const int content_column = 0;
300  views::ColumnSet* column_set = layout->AddColumnSet(content_column);
301  column_set->AddColumn(views::GridLayout::FILL,
302                        views::GridLayout::FILL,
303                        1,
304                        views::GridLayout::USE_PREF,
305                        0,
306                        0);
307
308  header_ = new PopupHeaderView(this);
309  layout->StartRow(1, content_column);
310  layout->AddView(header_);
311
312  layout->AddPaddingRow(1, kHeaderMarginBottom);
313  tabbed_pane_ = new views::TabbedPane(false);
314  layout->StartRow(1, content_column);
315  layout->AddView(tabbed_pane_);
316  // Tabs must be added after the tabbed_pane_ was added to the views
317  // hierachy.  Adding the |tabbed_pane_| to the views hierachy triggers the
318  // initialization of the native tab UI element. If the native tab UI
319  // element is not initalized adding a tab will result in a NULL pointer
320  // exception.
321  tabbed_pane_->AddTabAtIndex(
322      TAB_ID_PERMISSIONS,
323      l10n_util::GetStringUTF16(IDS_WEBSITE_SETTINGS_TAB_LABEL_PERMISSIONS),
324      CreatePermissionsTab());
325  connection_tab_ = CreateConnectionTab();
326  tabbed_pane_->AddTabAtIndex(
327      TAB_ID_CONNECTION,
328      l10n_util::GetStringUTF16(IDS_WEBSITE_SETTINGS_TAB_LABEL_CONNECTION),
329      connection_tab_);
330  DCHECK_EQ(tabbed_pane_->GetTabCount(), NUM_TAB_IDS);
331  tabbed_pane_->set_listener(this);
332
333  set_margins(gfx::Insets(kPopupMarginTop, kPopupMarginLeft,
334                          kPopupMarginBottom, kPopupMarginRight));
335
336  views::BubbleDelegateView::CreateBubble(this)->Show();
337  SizeToContents();
338
339  TabSpecificContentSettings* content_settings =
340      TabSpecificContentSettings::FromWebContents(web_contents);
341  InfoBarService* infobar_service =
342      InfoBarService::FromWebContents(web_contents);
343  presenter_.reset(new WebsiteSettings(this, profile,
344                                       content_settings,
345                                       infobar_service,
346                                       url,
347                                       ssl,
348                                       content::CertStore::GetInstance()));
349}
350
351void WebsiteSettingsPopupView::OnPermissionChanged(
352    PermissionSelectorView* permission_selector) {
353  DCHECK(permission_selector);
354  presenter_->OnSitePermissionChanged(permission_selector->type(),
355                                      permission_selector->current_setting());
356}
357
358void WebsiteSettingsPopupView::OnWidgetDestroying(views::Widget* widget) {
359  presenter_->OnUIClosing();
360}
361
362void WebsiteSettingsPopupView::ButtonPressed(
363    views::Button* button,
364    const ui::Event& event) {
365  GetWidget()->Close();
366}
367
368void WebsiteSettingsPopupView::LinkClicked(views::Link* source,
369                                           int event_flags) {
370  if (source == cookie_dialog_link_) {
371    // Count how often the Collected Cookies dialog is opened.
372    content::RecordAction(
373        content::UserMetricsAction("WebsiteSettings_CookiesDialogOpened"));
374    new CollectedCookiesViews(web_contents_);
375  } else if (source == certificate_dialog_link_) {
376    gfx::NativeWindow parent =
377        anchor_view() ? anchor_view()->GetWidget()->GetNativeWindow() : NULL;
378    ShowCertificateViewerByID(web_contents_, parent, cert_id_);
379  } else if (source == help_center_link_) {
380    browser_->OpenURL(content::OpenURLParams(
381        GURL(chrome::kPageInfoHelpCenterURL),
382        content::Referrer(),
383        NEW_FOREGROUND_TAB,
384        content::PAGE_TRANSITION_LINK,
385        false));
386  }
387  // The popup closes automatically when the collected cookies dialog or the
388  // certificate viewer opens.
389}
390
391void WebsiteSettingsPopupView::TabSelectedAt(int index) {
392  tabbed_pane_->GetSelectedTab()->Layout();
393  SizeToContents();
394}
395
396gfx::Size WebsiteSettingsPopupView::GetPreferredSize() {
397  if (header_ == NULL && tabbed_pane_ == NULL)
398    return views::View::GetPreferredSize();
399
400  int height = 0;
401  if (header_)
402    height += header_->GetPreferredSize().height();
403  if (tabbed_pane_)
404    height += tabbed_pane_->GetPreferredSize().height();
405
406  int width = kPermissionsSectionContentMinWidth;
407  if (site_data_content_)
408    width = std::max(width, site_data_content_->GetPreferredSize().width());
409  if (permissions_content_)
410    width = std::max(width, permissions_content_->GetPreferredSize().width());
411  width += kPermissionsSectionPaddingLeft;
412  width = std::min(width, kMaxPopupWidth);
413
414  return gfx::Size(width, height);
415}
416
417void WebsiteSettingsPopupView::SetCookieInfo(
418    const CookieInfoList& cookie_info_list) {
419  site_data_content_->RemoveAllChildViews(true);
420
421  views::GridLayout* layout = new views::GridLayout(site_data_content_);
422  site_data_content_->SetLayoutManager(layout);
423
424  const int site_data_content_column = 0;
425  views::ColumnSet* column_set =
426      layout->AddColumnSet(site_data_content_column);
427  column_set->AddColumn(views::GridLayout::FILL,
428                        views::GridLayout::FILL,
429                        1,
430                        views::GridLayout::FIXED,
431                        kSiteDataIconColumnWidth,
432                        0);
433  column_set->AddPaddingColumn(0, kIconMarginLeft);
434  column_set->AddColumn(views::GridLayout::FILL,
435                        views::GridLayout::FILL,
436                        1,
437                        views::GridLayout::USE_PREF,
438                        0,
439                        0);
440
441  layout->AddPaddingRow(1, 5);
442  for (CookieInfoList::const_iterator i(cookie_info_list.begin());
443       i != cookie_info_list.end();
444       ++i) {
445    string16 label_text = l10n_util::GetStringFUTF16(
446        IDS_WEBSITE_SETTINGS_SITE_DATA_STATS_LINE,
447        UTF8ToUTF16(i->cookie_source),
448        base::IntToString16(i->allowed),
449        base::IntToString16(i->blocked));
450    if (i != cookie_info_list.begin())
451      layout->AddPaddingRow(1, kSiteDataSectionRowSpacing);
452    layout->StartRow(1, site_data_content_column);
453    views::ImageView* icon = new views::ImageView();
454    const gfx::Image& image = WebsiteSettingsUI::GetPermissionIcon(
455        CONTENT_SETTINGS_TYPE_COOKIES, CONTENT_SETTING_ALLOW);
456    icon->SetImage(image.ToImageSkia());
457    layout->AddView(icon, 1, 1, views::GridLayout::CENTER,
458                    views::GridLayout::CENTER);
459    layout->AddView(new views::Label(label_text), 1, 1,
460                    views::GridLayout::LEADING, views::GridLayout::CENTER);
461  }
462  layout->AddPaddingRow(1, 6);
463
464  layout->Layout(site_data_content_);
465  SizeToContents();
466}
467
468void WebsiteSettingsPopupView::SetPermissionInfo(
469    const PermissionInfoList& permission_info_list) {
470  permissions_content_->RemoveAllChildViews(true);
471
472  views::GridLayout* layout =
473      new views::GridLayout(permissions_content_);
474  permissions_content_->SetLayoutManager(layout);
475  const int content_column = 0;
476  views::ColumnSet* column_set =
477      layout->AddColumnSet(content_column);
478  column_set->AddColumn(views::GridLayout::FILL,
479                        views::GridLayout::FILL,
480                        1,
481                        views::GridLayout::USE_PREF,
482                        0,
483                        0);
484  for (PermissionInfoList::const_iterator permission =
485           permission_info_list.begin();
486       permission != permission_info_list.end();
487       ++permission) {
488    layout->StartRow(1, content_column);
489    PermissionSelectorView* selector = new PermissionSelectorView(
490        web_contents_ ? web_contents_->GetURL() : GURL::EmptyGURL(),
491        permission->type,
492        permission->default_setting,
493        permission->setting,
494        permission->source);
495    selector->AddObserver(this);
496    layout->AddView(selector,
497                    1,
498                    1,
499                    views::GridLayout::LEADING,
500                    views::GridLayout::CENTER);
501    layout->AddPaddingRow(1, kPermissionsSectionRowSpacing);
502  }
503
504  SizeToContents();
505}
506
507void WebsiteSettingsPopupView::SetIdentityInfo(
508    const IdentityInfo& identity_info) {
509  string16 identity_status_text;
510  SkColor text_color = SK_ColorBLACK;
511  switch (identity_info.identity_status) {
512    case WebsiteSettings::SITE_IDENTITY_STATUS_CERT:
513    case WebsiteSettings::SITE_IDENTITY_STATUS_EV_CERT:
514      identity_status_text =
515          l10n_util::GetStringUTF16(IDS_WEBSITE_SETTINGS_IDENTITY_VERIFIED);
516      text_color = kIdentityVerifiedTextColor;
517      break;
518    case WebsiteSettings::SITE_IDENTITY_STATUS_ADMIN_PROVIDED_CERT:
519      identity_status_text =
520          l10n_util::GetStringUTF16(IDS_CERT_POLICY_PROVIDED_CERT_HEADER);
521      break;
522    default:
523      identity_status_text =
524         l10n_util::GetStringUTF16(IDS_WEBSITE_SETTINGS_IDENTITY_NOT_VERIFIED);
525      break;
526  }
527  header_->SetIdentityName(UTF8ToUTF16(identity_info.site_identity));
528  header_->SetIdentityStatus(identity_status_text, text_color);
529
530  // The headline and the certificate dialog link of the site's identity
531  // section is only displayed if the site's identity was verified. If the
532  // site's identity was verified, then the headline contains the organization
533  // name from the provided certificate. If the organization name is not
534  // available than the hostname of the site is used instead.
535  string16 headline;
536  if (identity_info.cert_id) {
537    cert_id_ = identity_info.cert_id;
538    certificate_dialog_link_ = new views::Link(
539        l10n_util::GetStringUTF16(IDS_PAGEINFO_CERT_INFO_BUTTON));
540    certificate_dialog_link_->set_listener(this);
541    headline = UTF8ToUTF16(identity_info.site_identity);
542  }
543  ResetConnectionSection(
544      identity_info_content_,
545      WebsiteSettingsUI::GetIdentityIcon(identity_info.identity_status),
546      string16(), // The identity section has no headline.
547      UTF8ToUTF16(identity_info.identity_status_description),
548      certificate_dialog_link_);
549
550  ResetConnectionSection(
551      connection_info_content_,
552      WebsiteSettingsUI::GetConnectionIcon(identity_info.connection_status),
553      string16(),  // The connection section has no headline.
554      UTF8ToUTF16(identity_info.connection_status_description),
555      NULL);
556
557  connection_tab_->InvalidateLayout();
558  Layout();
559  SizeToContents();
560}
561
562void WebsiteSettingsPopupView::SetFirstVisit(const string16& first_visit) {
563  ResetConnectionSection(
564      page_info_content_,
565      WebsiteSettingsUI::GetFirstVisitIcon(first_visit),
566      l10n_util::GetStringUTF16(IDS_PAGE_INFO_SITE_INFO_TITLE),
567      first_visit,
568      NULL);
569  connection_tab_->InvalidateLayout();
570  Layout();
571  SizeToContents();
572}
573
574void WebsiteSettingsPopupView::SetSelectedTab(TabId tab_id) {
575  tabbed_pane_->SelectTabAt(tab_id);
576}
577
578views::View* WebsiteSettingsPopupView::CreatePermissionsTab() {
579  views::View* pane = new views::View();
580  pane->SetLayoutManager(
581      new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 1));
582  // Add cookies and site data section.
583  cookie_dialog_link_ = new views::Link(
584      l10n_util::GetStringUTF16(IDS_WEBSITE_SETTINGS_SHOW_SITE_DATA));
585  cookie_dialog_link_->set_listener(this);
586  site_data_content_ = new views::View();
587  views::View* site_data_section =
588      CreateSection(l10n_util::GetStringUTF16(
589                        IDS_WEBSITE_SETTINGS_TITLE_SITE_DATA),
590                    site_data_content_,
591                    cookie_dialog_link_);
592  pane->AddChildView(site_data_section);
593  // Add permissions section.
594  permissions_content_ = new views::View();
595  views::View* permissions_section =
596      CreateSection(l10n_util::GetStringUTF16(
597                        IDS_WEBSITE_SETTINGS_TITLE_SITE_PERMISSIONS),
598                    permissions_content_,
599                    NULL);
600  pane->AddChildView(permissions_section);
601  return pane;
602}
603
604views::View* WebsiteSettingsPopupView::CreateConnectionTab() {
605  views::View* pane = new views::View();
606  pane->SetLayoutManager(
607      new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 1));
608  // Add site identity section.
609  identity_info_content_ = new views::View();
610  pane->AddChildView(identity_info_content_);
611
612  // Add connection section.
613  pane->AddChildView(new views::Separator(views::Separator::HORIZONTAL));
614  connection_info_content_ = new views::View();
615  pane->AddChildView(connection_info_content_);
616
617  // Add page info section.
618  pane->AddChildView(new views::Separator(views::Separator::HORIZONTAL));
619  page_info_content_ = new views::View();
620  pane->AddChildView(page_info_content_);
621
622  // Add help center link.
623  pane->AddChildView(new views::Separator(views::Separator::HORIZONTAL));
624  help_center_link_ = new views::Link(
625      l10n_util::GetStringUTF16(IDS_PAGE_INFO_HELP_CENTER_LINK));
626  help_center_link_->set_listener(this);
627  views::View* link_section = new views::View();
628  const int kLinkMarginTop = 4;
629  link_section->SetLayoutManager(
630      new views::BoxLayout(views::BoxLayout::kHorizontal,
631                           kConnectionSectionPaddingLeft,
632                           kLinkMarginTop,
633                           0));
634  link_section->AddChildView(help_center_link_);
635  pane->AddChildView(link_section);
636  return pane;
637}
638
639views::View* WebsiteSettingsPopupView::CreateSection(
640    const string16& headline_text,
641    views::View* content,
642    views::Link* link) {
643  views::View* container = new views::View();
644  views::GridLayout* layout = new views::GridLayout(container);
645  container->SetLayoutManager(layout);
646  const int content_column = 0;
647  views::ColumnSet* column_set = layout->AddColumnSet(content_column);
648  column_set->AddPaddingColumn(0, kPermissionsSectionPaddingLeft);
649  column_set->AddColumn(views::GridLayout::FILL,
650                        views::GridLayout::FILL,
651                        1,
652                        views::GridLayout::USE_PREF,
653                        0,
654                        0);
655
656  layout->AddPaddingRow(1, kPermissionsSectionPaddingTop);
657  layout->StartRow(1, content_column);
658  views::Label* headline = new views::Label(headline_text);
659  headline->SetFont(headline->font().DeriveFont(0, gfx::Font::BOLD));
660  layout->AddView(headline, 1, 1, views::GridLayout::LEADING,
661                  views::GridLayout::CENTER);
662
663  layout->AddPaddingRow(1, kPermissionsSectionHeadlineMarginBottom);
664  layout->StartRow(1, content_column);
665  layout->AddView(content, 1, 1, views::GridLayout::LEADING,
666                  views::GridLayout::CENTER);
667
668  if (link) {
669    layout->AddPaddingRow(1, 4);
670    layout->StartRow(1, content_column);
671    layout->AddView(link, 1, 1, views::GridLayout::LEADING,
672                    views::GridLayout::CENTER);
673  }
674
675  layout->AddPaddingRow(1, kPermissionsSectionPaddingBottom);
676  return container;
677}
678
679void WebsiteSettingsPopupView::ResetConnectionSection(
680    views::View* section_container,
681    const gfx::Image& icon,
682    const string16& headline,
683    const string16& text,
684    views::Link* link) {
685  section_container->RemoveAllChildViews(true);
686
687  views::GridLayout* layout = new views::GridLayout(section_container);
688  section_container->SetLayoutManager(layout);
689  views::ColumnSet* column_set = layout->AddColumnSet(0);
690  column_set->AddPaddingColumn(0, kConnectionSectionPaddingLeft);
691  column_set->AddColumn(views::GridLayout::LEADING,
692                        views::GridLayout::LEADING,
693                        0,
694                        views::GridLayout::USE_PREF,
695                        0,
696                        0);
697  column_set->AddPaddingColumn(0, kIconMarginLeft);
698  column_set->AddColumn(views::GridLayout::FILL,
699                        views::GridLayout::FILL,
700                        1,
701                        views::GridLayout::USE_PREF,
702                        0,
703                        0);
704  column_set->AddPaddingColumn(0, kConnectionSectionPaddingRight);
705
706
707  layout->AddPaddingRow(0, kConnectionSectionPaddingTop);
708  layout->StartRow(1, 0);
709
710  // Add status icon.
711  views::ImageView* icon_view = new views::ImageView();
712  icon_view->SetImage(*icon.ToImageSkia());
713  layout->AddView(icon_view, 1, 1, views::GridLayout::LEADING,
714                  views::GridLayout::LEADING);
715
716  // Add section content.
717  views::View* content_pane = new views::View();
718  views::GridLayout* content_layout = new views::GridLayout(content_pane);
719  content_pane->SetLayoutManager(content_layout);
720  views::ColumnSet* content_column_set = content_layout->AddColumnSet(0);
721  content_column_set->AddColumn(views::GridLayout::LEADING,
722                                views::GridLayout::LEADING,
723                                1,
724                                views::GridLayout::USE_PREF,
725                                0,
726                                0);
727  if (!headline.empty()) {
728    views::Label* headline_label = new views::Label(headline);
729    headline_label->SetFont(
730        headline_label->font().DeriveFont(0, gfx::Font::BOLD));
731    headline_label->SetMultiLine(true);
732    headline_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
733    // Allow linebreaking in the middle of words if necessary, so that extremely
734    // long hostnames (longer than one line) will still be completely shown.
735    headline_label->SetAllowCharacterBreak(true);
736    content_layout->StartRow(1, 0);
737    content_layout->AddView(headline_label);
738  }
739
740  views::Label* description_label = new views::Label(text);
741  description_label->SetMultiLine(true);
742  description_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
743  description_label->SetAllowCharacterBreak(true);
744  content_layout->StartRow(1, 0);
745  content_layout->AddView(description_label);
746
747  if (link) {
748    content_layout->StartRow(1, 0);
749    content_layout->AddView(link);
750  }
751
752  layout->AddView(content_pane, 1, 1, views::GridLayout::LEADING,
753                  views::GridLayout::LEADING);
754  layout->AddPaddingRow(0, kConnectionSectionPaddingBottom);
755}
756