- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / views / website_settings / website_settings_popup_view.cc
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
50 namespace {
51
52 // Padding values for sections on the connection tab.
53 const int kConnectionSectionPaddingBottom = 16;
54 const int kConnectionSectionPaddingLeft = 18;
55 const int kConnectionSectionPaddingTop = 16;
56 const int kConnectionSectionPaddingRight = 18;
57
58 // Font size of the label for the site identity.
59 const 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.
62 const int kIdentityVerifiedTextColor = 0xFF298a27;
63
64 // Left icon margin.
65 const int kIconMarginLeft = 6;
66
67 // Margin and padding values for the |PopupHeaderView|.
68 const int kHeaderMarginBottom = 10;
69 const int kHeaderPaddingBottom = 12;
70 const int kHeaderPaddingLeft = 18;
71 const int kHeaderPaddingRight = 8;
72 const int kHeaderPaddingTop = 12;
73
74 // Spacing between the site identity label and the site identity status text in
75 // the popup header.
76 const 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.
80 const int kLocationIconVerticalMargin = 5;
81
82 // The max possible width of the popup.
83 const int kMaxPopupWidth = 500;
84
85 // The margins between the popup border and the popup content.
86 const int kPopupMarginTop = 4;
87 const int kPopupMarginLeft = 0;
88 const int kPopupMarginBottom = 10;
89 const int kPopupMarginRight = 0;
90
91 // Padding values for sections on the permissions tab.
92 const int kPermissionsSectionContentMinWidth = 300;
93 const int kPermissionsSectionPaddingBottom = 6;
94 const int kPermissionsSectionPaddingLeft = 18;
95 const int kPermissionsSectionPaddingTop = 16;
96
97 // Space between the headline and the content of a section on the permissions
98 // tab.
99 const 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.
103 const int kPermissionsSectionRowSpacing = 2;
104
105 const int kSiteDataIconColumnWidth = 20;
106 const 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.
113 class 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.
137 class 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
150 PopupHeaderView::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
206 PopupHeaderView::~PopupHeaderView() {
207 }
208
209 void PopupHeaderView::SetIdentityName(const string16& name) {
210   name_->SetText(name);
211 }
212
213 void 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
223 InternalPageInfoPopupView::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
248 InternalPageInfoPopupView::~InternalPageInfoPopupView() {
249 }
250
251 ////////////////////////////////////////////////////////////////////////////////
252 // WebsiteSettingsPopupView
253 ////////////////////////////////////////////////////////////////////////////////
254
255 WebsiteSettingsPopupView::~WebsiteSettingsPopupView() {
256 }
257
258 // static
259 void 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
273 WebsiteSettingsPopupView::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(false);
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
349 void WebsiteSettingsPopupView::OnPermissionChanged(
350     PermissionSelectorView* permission_selector) {
351   DCHECK(permission_selector);
352   presenter_->OnSitePermissionChanged(permission_selector->type(),
353                                       permission_selector->current_setting());
354 }
355
356 void WebsiteSettingsPopupView::OnWidgetDestroying(views::Widget* widget) {
357   presenter_->OnUIClosing();
358 }
359
360 void WebsiteSettingsPopupView::ButtonPressed(
361     views::Button* button,
362     const ui::Event& event) {
363   GetWidget()->Close();
364 }
365
366 void 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
377 void WebsiteSettingsPopupView::TabSelectedAt(int index) {
378   tabbed_pane_->GetSelectedTab()->Layout();
379   SizeToContents();
380 }
381
382 gfx::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
403 void 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
454 void 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
493 void 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
548 void 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
560 void WebsiteSettingsPopupView::SetSelectedTab(TabId tab_id) {
561   tabbed_pane_->SelectTabAt(tab_id);
562 }
563
564 views::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
590 views::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
625 views::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
665 void 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.
746 void 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 }