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