Update To 11.40.268.0
[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 <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/url_constants.h"
21 #include "chrome/grit/chromium_strings.h"
22 #include "chrome/grit/generated_resources.h"
23 #include "components/content_settings/core/common/content_settings_types.h"
24 #include "content/public/browser/browser_thread.h"
25 #include "content/public/browser/cert_store.h"
26 #include "content/public/browser/user_metrics.h"
27 #include "grit/theme_resources.h"
28 #include "ui/base/l10n/l10n_util.h"
29 #include "ui/base/models/simple_menu_model.h"
30 #include "ui/base/resource/resource_bundle.h"
31 #include "ui/gfx/canvas.h"
32 #include "ui/gfx/font_list.h"
33 #include "ui/gfx/image/image.h"
34 #include "ui/gfx/insets.h"
35 #include "ui/resources/grit/ui_resources.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
53 namespace {
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.
61 bool is_popup_showing = false;
62
63 // Padding values for sections on the connection tab.
64 const int kConnectionSectionPaddingBottom = 16;
65 const int kConnectionSectionPaddingLeft = 18;
66 const int kConnectionSectionPaddingTop = 16;
67 const 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.
71 const SkColor kIdentityVerifiedTextColor = 0xFF298a27;
72
73 // Left icon margin.
74 const int kIconMarginLeft = 6;
75
76 // Margin and padding values for the |PopupHeaderView|.
77 const int kHeaderMarginBottom = 10;
78 const int kHeaderPaddingBottom = 12;
79 const int kHeaderPaddingLeft = 18;
80 const int kHeaderPaddingRight = 8;
81 const int kHeaderPaddingTop = 12;
82
83 // Spacing between the site identity label and the site identity status text in
84 // the popup header.
85 const 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.
89 const int kLocationIconVerticalMargin = 5;
90
91 // The max possible width of the popup.
92 const int kMaxPopupWidth = 500;
93
94 // The margins between the popup border and the popup content.
95 const int kPopupMarginTop = 4;
96 const int kPopupMarginLeft = 0;
97 const int kPopupMarginBottom = 10;
98 const int kPopupMarginRight = 0;
99
100 // Padding values for sections on the permissions tab.
101 const int kPermissionsSectionContentMinWidth = 300;
102 const int kPermissionsSectionPaddingBottom = 6;
103 const int kPermissionsSectionPaddingLeft = 18;
104 const int kPermissionsSectionPaddingTop = 16;
105
106 // Space between the headline and the content of a section on the permissions
107 // tab.
108 const 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.
112 const int kPermissionsSectionRowSpacing = 2;
113
114 const int kSiteDataIconColumnWidth = 20;
115 const 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.
122 class PopupHeaderView : public views::View {
123  public:
124   explicit PopupHeaderView(views::ButtonListener* close_button_listener);
125   ~PopupHeaderView() override;
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.
146 class InternalPageInfoPopupView : public views::BubbleDelegateView {
147  public:
148   explicit InternalPageInfoPopupView(views::View* anchor_view);
149   ~InternalPageInfoPopupView() override;
150
151   // views::BubbleDelegateView:
152   void OnWidgetDestroying(views::Widget* widget) override;
153
154  private:
155   DISALLOW_COPY_AND_ASSIGN(InternalPageInfoPopupView);
156 };
157
158 ////////////////////////////////////////////////////////////////////////////////
159 // Popup Header
160 ////////////////////////////////////////////////////////////////////////////////
161
162 PopupHeaderView::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
217 PopupHeaderView::~PopupHeaderView() {
218 }
219
220 void PopupHeaderView::SetIdentityName(const base::string16& name) {
221   name_->SetText(name);
222 }
223
224 void 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
234 InternalPageInfoPopupView::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
259 InternalPageInfoPopupView::~InternalPageInfoPopupView() {
260 }
261
262 void InternalPageInfoPopupView::OnWidgetDestroying(views::Widget* widget) {
263   is_popup_showing = false;
264 }
265
266 ////////////////////////////////////////////////////////////////////////////////
267 // WebsiteSettingsPopupView
268 ////////////////////////////////////////////////////////////////////////////////
269
270 WebsiteSettingsPopupView::~WebsiteSettingsPopupView() {
271 }
272
273 // static
274 void 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
290 bool WebsiteSettingsPopupView::IsPopupShowing() {
291   return is_popup_showing;
292 }
293
294 WebsiteSettingsPopupView::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       reset_decisions_button_(NULL),
314       cert_id_(0),
315       help_center_link_(NULL),
316       connection_info_content_(NULL),
317       page_info_content_(NULL),
318       weak_factory_(this) {
319   // Compensate for built-in vertical padding in the anchor view's image.
320   set_anchor_view_insets(gfx::Insets(kLocationIconVerticalMargin, 0,
321                                      kLocationIconVerticalMargin, 0));
322
323   views::GridLayout* layout = new views::GridLayout(this);
324   SetLayoutManager(layout);
325   const int content_column = 0;
326   views::ColumnSet* column_set = layout->AddColumnSet(content_column);
327   column_set->AddColumn(views::GridLayout::FILL,
328                         views::GridLayout::FILL,
329                         1,
330                         views::GridLayout::USE_PREF,
331                         0,
332                         0);
333
334   header_ = new PopupHeaderView(this);
335   layout->StartRow(1, content_column);
336   layout->AddView(header_);
337
338   layout->AddPaddingRow(1, kHeaderMarginBottom);
339   tabbed_pane_ = new views::TabbedPane();
340   layout->StartRow(1, content_column);
341   layout->AddView(tabbed_pane_);
342   // Tabs must be added after the tabbed_pane_ was added to the views
343   // hierachy.  Adding the |tabbed_pane_| to the views hierachy triggers the
344   // initialization of the native tab UI element. If the native tab UI
345   // element is not initalized adding a tab will result in a NULL pointer
346   // exception.
347   tabbed_pane_->AddTabAtIndex(
348       TAB_ID_PERMISSIONS,
349       l10n_util::GetStringUTF16(IDS_WEBSITE_SETTINGS_TAB_LABEL_PERMISSIONS),
350       CreatePermissionsTab());
351   connection_tab_ = CreateConnectionTab();
352   tabbed_pane_->AddTabAtIndex(
353       TAB_ID_CONNECTION,
354       l10n_util::GetStringUTF16(IDS_WEBSITE_SETTINGS_TAB_LABEL_CONNECTION),
355       connection_tab_);
356   DCHECK_EQ(tabbed_pane_->GetTabCount(), NUM_TAB_IDS);
357   tabbed_pane_->set_listener(this);
358
359   set_margins(gfx::Insets(kPopupMarginTop, kPopupMarginLeft,
360                           kPopupMarginBottom, kPopupMarginRight));
361
362   views::BubbleDelegateView::CreateBubble(this)->Show();
363   SizeToContents();
364
365   presenter_.reset(new WebsiteSettings(
366       this, profile,
367       TabSpecificContentSettings::FromWebContents(web_contents),
368       InfoBarService::FromWebContents(web_contents), url, ssl,
369       content::CertStore::GetInstance()));
370 }
371
372 void WebsiteSettingsPopupView::OnPermissionChanged(
373     const WebsiteSettingsUI::PermissionInfo& permission) {
374   presenter_->OnSitePermissionChanged(permission.type, permission.setting);
375 }
376
377 void WebsiteSettingsPopupView::OnWidgetDestroying(views::Widget* widget) {
378   is_popup_showing = false;
379   presenter_->OnUIClosing();
380 }
381
382 void WebsiteSettingsPopupView::ButtonPressed(views::Button* button,
383                                              const ui::Event& event) {
384   if (button == reset_decisions_button_)
385     presenter_->OnRevokeSSLErrorBypassButtonPressed();
386   GetWidget()->Close();
387 }
388
389 void WebsiteSettingsPopupView::LinkClicked(views::Link* source,
390                                            int event_flags) {
391   if (source == cookie_dialog_link_) {
392     // Count how often the Collected Cookies dialog is opened.
393     presenter_->RecordWebsiteSettingsAction(
394         WebsiteSettings::WEBSITE_SETTINGS_COOKIES_DIALOG_OPENED);
395
396     new CollectedCookiesViews(web_contents_);
397   } else if (source == certificate_dialog_link_) {
398     gfx::NativeWindow parent = GetAnchorView() ?
399         GetAnchorView()->GetWidget()->GetNativeWindow() : NULL;
400     presenter_->RecordWebsiteSettingsAction(
401         WebsiteSettings::WEBSITE_SETTINGS_CERTIFICATE_DIALOG_OPENED);
402     ShowCertificateViewerByID(web_contents_, parent, cert_id_);
403   } else if (source == signed_certificate_timestamps_link_) {
404     chrome::ShowSignedCertificateTimestampsViewer(
405         web_contents_, signed_certificate_timestamp_ids_);
406     presenter_->RecordWebsiteSettingsAction(
407         WebsiteSettings::WEBSITE_SETTINGS_TRANSPARENCY_VIEWER_OPENED);
408   } else if (source == help_center_link_) {
409     browser_->OpenURL(
410         content::OpenURLParams(GURL(chrome::kPageInfoHelpCenterURL),
411                                content::Referrer(),
412                                NEW_FOREGROUND_TAB,
413                                ui::PAGE_TRANSITION_LINK,
414                                false));
415     presenter_->RecordWebsiteSettingsAction(
416         WebsiteSettings::WEBSITE_SETTINGS_CONNECTION_HELP_OPENED);
417   }
418 }
419
420 void WebsiteSettingsPopupView::TabSelectedAt(int index) {
421   switch (index) {
422     case TAB_ID_PERMISSIONS:
423       presenter_->RecordWebsiteSettingsAction(
424           WebsiteSettings::WEBSITE_SETTINGS_PERMISSIONS_TAB_SELECTED);
425       break;
426     case TAB_ID_CONNECTION:
427       // If the Connection tab is selected first, we're still inside the
428       // construction of presenter_. In that case, the action is already logged
429       // by WEBSITE_SETTINGS_CONNECTION_TAB_SHOWN_IMMEDIATELY.
430       if (presenter_) {
431         presenter_->RecordWebsiteSettingsAction(
432             WebsiteSettings::WEBSITE_SETTINGS_CONNECTION_TAB_SELECTED);
433       }
434       break;
435     default:
436       NOTREACHED();
437   }
438   tabbed_pane_->GetSelectedTab()->Layout();
439   SizeToContents();
440 }
441
442 gfx::Size WebsiteSettingsPopupView::GetPreferredSize() const {
443   if (header_ == NULL && tabbed_pane_ == NULL)
444     return views::View::GetPreferredSize();
445
446   int height = 0;
447   if (header_)
448     height += header_->GetPreferredSize().height();
449   if (tabbed_pane_)
450     height += tabbed_pane_->GetPreferredSize().height();
451
452   int width = kPermissionsSectionContentMinWidth;
453   if (site_data_content_)
454     width = std::max(width, site_data_content_->GetPreferredSize().width());
455   if (permissions_content_)
456     width = std::max(width, permissions_content_->GetPreferredSize().width());
457   width += kPermissionsSectionPaddingLeft;
458   width = std::min(width, kMaxPopupWidth);
459
460   return gfx::Size(width, height);
461 }
462
463 void WebsiteSettingsPopupView::SetCookieInfo(
464     const CookieInfoList& cookie_info_list) {
465   site_data_content_->RemoveAllChildViews(true);
466
467   views::GridLayout* layout = new views::GridLayout(site_data_content_);
468   site_data_content_->SetLayoutManager(layout);
469
470   const int site_data_content_column = 0;
471   views::ColumnSet* column_set =
472       layout->AddColumnSet(site_data_content_column);
473   column_set->AddColumn(views::GridLayout::FILL,
474                         views::GridLayout::FILL,
475                         1,
476                         views::GridLayout::FIXED,
477                         kSiteDataIconColumnWidth,
478                         0);
479   column_set->AddPaddingColumn(0, kIconMarginLeft);
480   column_set->AddColumn(views::GridLayout::FILL,
481                         views::GridLayout::FILL,
482                         1,
483                         views::GridLayout::USE_PREF,
484                         0,
485                         0);
486
487   layout->AddPaddingRow(1, 5);
488   for (CookieInfoList::const_iterator i(cookie_info_list.begin());
489        i != cookie_info_list.end();
490        ++i) {
491     base::string16 label_text = l10n_util::GetStringFUTF16(
492         IDS_WEBSITE_SETTINGS_SITE_DATA_STATS_LINE,
493         base::UTF8ToUTF16(i->cookie_source),
494         base::IntToString16(i->allowed),
495         base::IntToString16(i->blocked));
496     if (i != cookie_info_list.begin())
497       layout->AddPaddingRow(1, kSiteDataSectionRowSpacing);
498     layout->StartRow(1, site_data_content_column);
499     WebsiteSettingsUI::PermissionInfo info;
500     info.type = CONTENT_SETTINGS_TYPE_COOKIES;
501     info.setting = CONTENT_SETTING_ALLOW;
502     views::ImageView* icon = new views::ImageView();
503     const gfx::Image& image = WebsiteSettingsUI::GetPermissionIcon(info);
504     icon->SetImage(image.ToImageSkia());
505     layout->AddView(icon, 1, 1, views::GridLayout::CENTER,
506                     views::GridLayout::CENTER);
507     layout->AddView(new views::Label(label_text), 1, 1,
508                     views::GridLayout::LEADING, views::GridLayout::CENTER);
509   }
510   layout->AddPaddingRow(1, 6);
511
512   layout->Layout(site_data_content_);
513   SizeToContents();
514 }
515
516 void WebsiteSettingsPopupView::SetPermissionInfo(
517     const PermissionInfoList& permission_info_list) {
518   permissions_content_->RemoveAllChildViews(true);
519
520   views::GridLayout* layout =
521       new views::GridLayout(permissions_content_);
522   permissions_content_->SetLayoutManager(layout);
523   const int content_column = 0;
524   views::ColumnSet* column_set =
525       layout->AddColumnSet(content_column);
526   column_set->AddColumn(views::GridLayout::FILL,
527                         views::GridLayout::FILL,
528                         1,
529                         views::GridLayout::USE_PREF,
530                         0,
531                         0);
532   for (PermissionInfoList::const_iterator permission =
533            permission_info_list.begin();
534        permission != permission_info_list.end();
535        ++permission) {
536     layout->StartRow(1, content_column);
537     PermissionSelectorView* selector = new PermissionSelectorView(
538         web_contents_ ? web_contents_->GetURL() : GURL::EmptyGURL(),
539         *permission);
540     selector->AddObserver(this);
541     layout->AddView(selector,
542                     1,
543                     1,
544                     views::GridLayout::LEADING,
545                     views::GridLayout::CENTER);
546     layout->AddPaddingRow(1, kPermissionsSectionRowSpacing);
547   }
548
549   SizeToContents();
550 }
551
552 void WebsiteSettingsPopupView::SetIdentityInfo(
553     const IdentityInfo& identity_info) {
554   base::string16 identity_status_text;
555   SkColor text_color = SK_ColorBLACK;
556   switch (identity_info.identity_status) {
557     case WebsiteSettings::SITE_IDENTITY_STATUS_CERT:
558     case WebsiteSettings::SITE_IDENTITY_STATUS_EV_CERT:
559       identity_status_text =
560           l10n_util::GetStringUTF16(IDS_WEBSITE_SETTINGS_IDENTITY_VERIFIED);
561       text_color = kIdentityVerifiedTextColor;
562       break;
563     case WebsiteSettings::SITE_IDENTITY_STATUS_ADMIN_PROVIDED_CERT:
564       identity_status_text =
565           l10n_util::GetStringUTF16(IDS_CERT_POLICY_PROVIDED_CERT_HEADER);
566       break;
567     default:
568       identity_status_text =
569          l10n_util::GetStringUTF16(IDS_WEBSITE_SETTINGS_IDENTITY_NOT_VERIFIED);
570       break;
571   }
572   header_->SetIdentityName(base::UTF8ToUTF16(identity_info.site_identity));
573   header_->SetIdentityStatus(identity_status_text, text_color);
574
575   // The headline and the certificate dialog link of the site's identity
576   // section is only displayed if the site's identity was verified. If the
577   // site's identity was verified, then the headline contains the organization
578   // name from the provided certificate. If the organization name is not
579   // available than the hostname of the site is used instead.
580   base::string16 headline;
581   if (identity_info.cert_id) {
582     cert_id_ = identity_info.cert_id;
583     signed_certificate_timestamp_ids_.assign(
584         identity_info.signed_certificate_timestamp_ids.begin(),
585         identity_info.signed_certificate_timestamp_ids.end());
586
587     certificate_dialog_link_ = new views::Link(
588         l10n_util::GetStringUTF16(IDS_PAGEINFO_CERT_INFO_BUTTON));
589     certificate_dialog_link_->set_listener(this);
590
591     if (!signed_certificate_timestamp_ids_.empty()) {
592       signed_certificate_timestamps_link_ =
593           new views::Link(l10n_util::GetStringUTF16(
594               IDS_PAGEINFO_CERT_TRANSPARENCY_INFO_BUTTON));
595       signed_certificate_timestamps_link_->set_listener(this);
596     }
597
598     if (identity_info.show_ssl_decision_revoke_button) {
599       reset_decisions_button_ = new views::LabelButton(
600           this,
601           l10n_util::GetStringUTF16(
602               IDS_PAGEINFO_RESET_INVALID_CERTIFICATE_DECISIONS_BUTTON));
603       reset_decisions_button_->SetStyle(views::Button::STYLE_BUTTON);
604     }
605
606     headline = base::UTF8ToUTF16(identity_info.site_identity);
607   }
608   ResetConnectionSection(
609       identity_info_content_,
610       WebsiteSettingsUI::GetIdentityIcon(identity_info.identity_status),
611       base::string16(),  // The identity section has no headline.
612       base::UTF8ToUTF16(identity_info.identity_status_description),
613       certificate_dialog_link_,
614       signed_certificate_timestamps_link_,
615       reset_decisions_button_);
616
617   ResetConnectionSection(
618       connection_info_content_,
619       WebsiteSettingsUI::GetConnectionIcon(identity_info.connection_status),
620       base::string16(),  // The connection section has no headline.
621       base::UTF8ToUTF16(identity_info.connection_status_description),
622       NULL,
623       NULL,
624       NULL);
625
626   connection_tab_->InvalidateLayout();
627   Layout();
628   SizeToContents();
629 }
630
631 void WebsiteSettingsPopupView::SetFirstVisit(
632     const base::string16& first_visit) {
633   ResetConnectionSection(
634       page_info_content_,
635       WebsiteSettingsUI::GetFirstVisitIcon(first_visit),
636       l10n_util::GetStringUTF16(IDS_PAGE_INFO_SITE_INFO_TITLE),
637       first_visit,
638       NULL,
639       NULL,
640       NULL);
641   connection_tab_->InvalidateLayout();
642   Layout();
643   SizeToContents();
644 }
645
646 void WebsiteSettingsPopupView::SetSelectedTab(TabId tab_id) {
647   tabbed_pane_->SelectTabAt(tab_id);
648 }
649
650 views::View* WebsiteSettingsPopupView::CreatePermissionsTab() {
651   views::View* pane = new views::View();
652   pane->SetLayoutManager(
653       new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 1));
654   // Add cookies and site data section.
655   cookie_dialog_link_ = new views::Link(
656       l10n_util::GetStringUTF16(IDS_WEBSITE_SETTINGS_SHOW_SITE_DATA));
657   cookie_dialog_link_->set_listener(this);
658   site_data_content_ = new views::View();
659   views::View* site_data_section =
660       CreateSection(l10n_util::GetStringUTF16(
661                         IDS_WEBSITE_SETTINGS_TITLE_SITE_DATA),
662                     site_data_content_,
663                     cookie_dialog_link_);
664   pane->AddChildView(site_data_section);
665   // Add permissions section.
666   permissions_content_ = new views::View();
667   views::View* permissions_section =
668       CreateSection(l10n_util::GetStringUTF16(
669                         IDS_WEBSITE_SETTINGS_TITLE_SITE_PERMISSIONS),
670                     permissions_content_,
671                     NULL);
672   pane->AddChildView(permissions_section);
673   return pane;
674 }
675
676 views::View* WebsiteSettingsPopupView::CreateConnectionTab() {
677   views::View* pane = new views::View();
678   pane->SetLayoutManager(
679       new views::BoxLayout(views::BoxLayout::kVertical, 0, 0, 1));
680   // Add site identity section.
681   identity_info_content_ = new views::View();
682   pane->AddChildView(identity_info_content_);
683
684   // Add connection section.
685   pane->AddChildView(new views::Separator(views::Separator::HORIZONTAL));
686   connection_info_content_ = new views::View();
687   pane->AddChildView(connection_info_content_);
688
689   // Add page info section.
690   pane->AddChildView(new views::Separator(views::Separator::HORIZONTAL));
691   page_info_content_ = new views::View();
692   pane->AddChildView(page_info_content_);
693
694   // Add help center link.
695   pane->AddChildView(new views::Separator(views::Separator::HORIZONTAL));
696   help_center_link_ = new views::Link(
697       l10n_util::GetStringUTF16(IDS_PAGE_INFO_HELP_CENTER_LINK));
698   help_center_link_->set_listener(this);
699   views::View* link_section = new views::View();
700   const int kLinkMarginTop = 4;
701   link_section->SetLayoutManager(
702       new views::BoxLayout(views::BoxLayout::kHorizontal,
703                            kConnectionSectionPaddingLeft,
704                            kLinkMarginTop,
705                            0));
706   link_section->AddChildView(help_center_link_);
707   pane->AddChildView(link_section);
708   return pane;
709 }
710
711 views::View* WebsiteSettingsPopupView::CreateSection(
712     const base::string16& headline_text,
713     views::View* content,
714     views::Link* link) {
715   views::View* container = new views::View();
716   views::GridLayout* layout = new views::GridLayout(container);
717   container->SetLayoutManager(layout);
718   const int content_column = 0;
719   views::ColumnSet* column_set = layout->AddColumnSet(content_column);
720   column_set->AddPaddingColumn(0, kPermissionsSectionPaddingLeft);
721   column_set->AddColumn(views::GridLayout::FILL,
722                         views::GridLayout::FILL,
723                         1,
724                         views::GridLayout::USE_PREF,
725                         0,
726                         0);
727
728   layout->AddPaddingRow(1, kPermissionsSectionPaddingTop);
729   layout->StartRow(1, content_column);
730   ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
731   views::Label* headline = new views::Label(
732       headline_text, rb.GetFontList(ui::ResourceBundle::BoldFont));
733   layout->AddView(headline, 1, 1, views::GridLayout::LEADING,
734                   views::GridLayout::CENTER);
735
736   layout->AddPaddingRow(1, kPermissionsSectionHeadlineMarginBottom);
737   layout->StartRow(1, content_column);
738   layout->AddView(content, 1, 1, views::GridLayout::LEADING,
739                   views::GridLayout::CENTER);
740
741   if (link) {
742     layout->AddPaddingRow(1, 4);
743     layout->StartRow(1, content_column);
744     layout->AddView(link, 1, 1, views::GridLayout::LEADING,
745                     views::GridLayout::CENTER);
746   }
747
748   layout->AddPaddingRow(1, kPermissionsSectionPaddingBottom);
749   return container;
750 }
751
752 void WebsiteSettingsPopupView::ResetConnectionSection(
753     views::View* section_container,
754     const gfx::Image& icon,
755     const base::string16& headline,
756     const base::string16& text,
757     views::Link* link,
758     views::Link* secondary_link,
759     views::LabelButton* reset_decisions_button) {
760   section_container->RemoveAllChildViews(true);
761
762   views::GridLayout* layout = new views::GridLayout(section_container);
763   section_container->SetLayoutManager(layout);
764   views::ColumnSet* column_set = layout->AddColumnSet(0);
765   column_set->AddPaddingColumn(0, kConnectionSectionPaddingLeft);
766   column_set->AddColumn(views::GridLayout::LEADING,
767                         views::GridLayout::LEADING,
768                         0,
769                         views::GridLayout::USE_PREF,
770                         0,
771                         0);
772   column_set->AddPaddingColumn(0, kIconMarginLeft);
773   column_set->AddColumn(views::GridLayout::FILL,
774                         views::GridLayout::FILL,
775                         1,
776                         views::GridLayout::USE_PREF,
777                         0,
778                         0);
779   column_set->AddPaddingColumn(0, kConnectionSectionPaddingRight);
780
781
782   layout->AddPaddingRow(0, kConnectionSectionPaddingTop);
783   layout->StartRow(1, 0);
784
785   // Add status icon.
786   views::ImageView* icon_view = new views::ImageView();
787   icon_view->SetImage(*icon.ToImageSkia());
788   layout->AddView(icon_view, 1, 1, views::GridLayout::LEADING,
789                   views::GridLayout::LEADING);
790
791   // Add section content.
792   views::View* content_pane = new views::View();
793   views::GridLayout* content_layout = new views::GridLayout(content_pane);
794   content_pane->SetLayoutManager(content_layout);
795   views::ColumnSet* content_column_set = content_layout->AddColumnSet(0);
796   content_column_set->AddColumn(views::GridLayout::LEADING,
797                                 views::GridLayout::LEADING,
798                                 1,
799                                 views::GridLayout::USE_PREF,
800                                 0,
801                                 0);
802   if (!headline.empty()) {
803     ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
804     views::Label* headline_label = new views::Label(
805         headline, rb.GetFontList(ui::ResourceBundle::BoldFont));
806     headline_label->SetMultiLine(true);
807     headline_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
808     // Allow linebreaking in the middle of words if necessary, so that extremely
809     // long hostnames (longer than one line) will still be completely shown.
810     headline_label->SetAllowCharacterBreak(true);
811     content_layout->StartRow(1, 0);
812     content_layout->AddView(headline_label);
813   }
814
815   views::Label* description_label = new views::Label(text);
816   description_label->SetMultiLine(true);
817   description_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
818   description_label->SetAllowCharacterBreak(true);
819   content_layout->StartRow(1, 0);
820   content_layout->AddView(description_label);
821
822   if (link) {
823     content_layout->StartRow(1, 0);
824     content_layout->AddView(link);
825   }
826
827   if (secondary_link) {
828     content_layout->StartRow(1, 0);
829     content_layout->AddView(secondary_link);
830   }
831
832   if (reset_decisions_button) {
833     content_layout->StartRow(1, 0);
834     content_layout->AddView(reset_decisions_button);
835   }
836
837   layout->AddView(content_pane, 1, 1, views::GridLayout::LEADING,
838                   views::GridLayout::LEADING);
839   layout->AddPaddingRow(0, kConnectionSectionPaddingBottom);
840 }