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