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