Home | History | Annotate | Download | only in views
      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/collected_cookies_views.h"
      6 
      7 #include "base/prefs/pref_service.h"
      8 #include "chrome/browser/browsing_data/browsing_data_appcache_helper.h"
      9 #include "chrome/browser/browsing_data/browsing_data_cookie_helper.h"
     10 #include "chrome/browser/browsing_data/browsing_data_database_helper.h"
     11 #include "chrome/browser/browsing_data/browsing_data_file_system_helper.h"
     12 #include "chrome/browser/browsing_data/browsing_data_indexed_db_helper.h"
     13 #include "chrome/browser/browsing_data/browsing_data_local_storage_helper.h"
     14 #include "chrome/browser/browsing_data/browsing_data_server_bound_cert_helper.h"
     15 #include "chrome/browser/browsing_data/cookies_tree_model.h"
     16 #include "chrome/browser/chrome_notification_types.h"
     17 #include "chrome/browser/content_settings/cookie_settings.h"
     18 #include "chrome/browser/content_settings/local_shared_objects_container.h"
     19 #include "chrome/browser/content_settings/tab_specific_content_settings.h"
     20 #include "chrome/browser/infobars/infobar_service.h"
     21 #include "chrome/browser/profiles/profile.h"
     22 #include "chrome/browser/ui/collected_cookies_infobar_delegate.h"
     23 #include "chrome/browser/ui/views/constrained_window_views.h"
     24 #include "chrome/browser/ui/views/cookie_info_view.h"
     25 #include "chrome/common/pref_names.h"
     26 #include "components/web_modal/web_contents_modal_dialog_host.h"
     27 #include "components/web_modal/web_contents_modal_dialog_manager.h"
     28 #include "components/web_modal/web_contents_modal_dialog_manager_delegate.h"
     29 #include "content/public/browser/notification_details.h"
     30 #include "content/public/browser/notification_source.h"
     31 #include "content/public/browser/web_contents.h"
     32 #include "grit/generated_resources.h"
     33 #include "grit/locale_settings.h"
     34 #include "grit/theme_resources.h"
     35 #include "net/cookies/canonical_cookie.h"
     36 #include "ui/base/l10n/l10n_util.h"
     37 #include "ui/base/resource/resource_bundle.h"
     38 #include "ui/gfx/color_utils.h"
     39 #include "ui/views/border.h"
     40 #include "ui/views/controls/button/label_button.h"
     41 #include "ui/views/controls/image_view.h"
     42 #include "ui/views/controls/label.h"
     43 #include "ui/views/controls/scroll_view.h"
     44 #include "ui/views/controls/tabbed_pane/tabbed_pane.h"
     45 #include "ui/views/controls/tree/tree_view.h"
     46 #include "ui/views/layout/box_layout.h"
     47 #include "ui/views/layout/grid_layout.h"
     48 #include "ui/views/layout/layout_constants.h"
     49 #include "ui/views/widget/widget.h"
     50 #include "ui/views/window/dialog_delegate.h"
     51 
     52 using web_modal::WebContentsModalDialogManager;
     53 using web_modal::WebContentsModalDialogManagerDelegate;
     54 
     55 namespace chrome {
     56 
     57 // Declared in browser_dialogs.h so others don't have to depend on our header.
     58 void ShowCollectedCookiesDialog(content::WebContents* web_contents) {
     59   // Deletes itself on close.
     60   new CollectedCookiesViews(web_contents);
     61 }
     62 
     63 }  // namespace chrome
     64 
     65 namespace {
     66 
     67 // Spacing between the infobar frame and its contents.
     68 const int kInfobarVerticalPadding = 3;
     69 const int kInfobarHorizontalPadding = 8;
     70 
     71 // Width of the infobar frame.
     72 const int kInfobarBorderSize = 1;
     73 
     74 // Dimensions of the tree views.
     75 const int kTreeViewWidth = 400;
     76 const int kTreeViewHeight = 125;
     77 
     78 // The color of the border around the cookies tree view.
     79 const SkColor kCookiesBorderColor = SkColorSetRGB(0xC8, 0xC8, 0xC8);
     80 
     81 // Spacing constants used with the new dialog style.
     82 const int kTabbedPaneTopPadding = 14;
     83 const int kLabelBottomPadding = 17;
     84 const int kCookieInfoBottomPadding = 4;
     85 const int kVPanelPadding = 15;
     86 
     87 }  // namespace
     88 
     89 // A custom view that conditionally displays an infobar.
     90 class InfobarView : public views::View {
     91  public:
     92   InfobarView() {
     93     content_ = new views::View;
     94 #if defined(USE_AURA) || !defined(OS_WIN)
     95     SkColor border_color = SK_ColorGRAY;
     96 #else
     97     SkColor border_color = color_utils::GetSysSkColor(COLOR_3DSHADOW);
     98 #endif
     99     views::Border* border = views::Border::CreateSolidBorder(
    100         kInfobarBorderSize, border_color);
    101     content_->set_border(border);
    102 
    103     ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
    104     info_image_ = new views::ImageView();
    105     info_image_->SetImage(rb.GetImageSkiaNamed(IDR_INFO));
    106     label_ = new views::Label();
    107   }
    108   virtual ~InfobarView() {}
    109 
    110   // Update the visibility of the infobar. If |is_visible| is true, a rule for
    111   // |setting| on |domain_name| was created.
    112   void UpdateVisibility(bool is_visible,
    113                         ContentSetting setting,
    114                         const base::string16& domain_name) {
    115     if (!is_visible) {
    116       SetVisible(false);
    117       return;
    118     }
    119 
    120     base::string16 label;
    121     switch (setting) {
    122       case CONTENT_SETTING_BLOCK:
    123         label = l10n_util::GetStringFUTF16(
    124             IDS_COLLECTED_COOKIES_BLOCK_RULE_CREATED, domain_name);
    125         break;
    126 
    127       case CONTENT_SETTING_ALLOW:
    128         label = l10n_util::GetStringFUTF16(
    129             IDS_COLLECTED_COOKIES_ALLOW_RULE_CREATED, domain_name);
    130         break;
    131 
    132       case CONTENT_SETTING_SESSION_ONLY:
    133         label = l10n_util::GetStringFUTF16(
    134             IDS_COLLECTED_COOKIES_SESSION_RULE_CREATED, domain_name);
    135         break;
    136 
    137       default:
    138         NOTREACHED();
    139     }
    140     label_->SetText(label);
    141     content_->Layout();
    142     SetVisible(true);
    143   }
    144 
    145  private:
    146   // Initialize contents and layout.
    147   void Init() {
    148     AddChildView(content_);
    149     content_->SetLayoutManager(
    150         new views::BoxLayout(views::BoxLayout::kHorizontal,
    151                              kInfobarHorizontalPadding,
    152                              kInfobarVerticalPadding,
    153                              views::kRelatedControlSmallHorizontalSpacing));
    154     content_->AddChildView(info_image_);
    155     content_->AddChildView(label_);
    156     UpdateVisibility(false, CONTENT_SETTING_BLOCK, base::string16());
    157   }
    158 
    159   // views::View overrides.
    160   virtual gfx::Size GetPreferredSize() OVERRIDE {
    161     if (!visible())
    162       return gfx::Size();
    163 
    164     // Add space around the banner.
    165     gfx::Size size(content_->GetPreferredSize());
    166     size.Enlarge(0, 2 * views::kRelatedControlVerticalSpacing);
    167     return size;
    168   }
    169 
    170   virtual void Layout() OVERRIDE {
    171     content_->SetBounds(
    172         0, views::kRelatedControlVerticalSpacing,
    173         width(), height() - views::kRelatedControlVerticalSpacing);
    174   }
    175 
    176   virtual void ViewHierarchyChanged(
    177       const ViewHierarchyChangedDetails& details) OVERRIDE {
    178     if (details.is_add && details.child == this)
    179       Init();
    180   }
    181 
    182   // Holds the info icon image and text label and renders the border.
    183   views::View* content_;
    184   // Info icon image.
    185   views::ImageView* info_image_;
    186   // The label responsible for rendering the text.
    187   views::Label* label_;
    188 
    189   DISALLOW_COPY_AND_ASSIGN(InfobarView);
    190 };
    191 
    192 ///////////////////////////////////////////////////////////////////////////////
    193 // CollectedCookiesViews, public:
    194 
    195 CollectedCookiesViews::CollectedCookiesViews(content::WebContents* web_contents)
    196     : web_contents_(web_contents),
    197       allowed_label_(NULL),
    198       blocked_label_(NULL),
    199       allowed_cookies_tree_(NULL),
    200       blocked_cookies_tree_(NULL),
    201       block_allowed_button_(NULL),
    202       allow_blocked_button_(NULL),
    203       for_session_blocked_button_(NULL),
    204       cookie_info_view_(NULL),
    205       infobar_(NULL),
    206       status_changed_(false) {
    207   TabSpecificContentSettings* content_settings =
    208       TabSpecificContentSettings::FromWebContents(web_contents);
    209   registrar_.Add(this, chrome::NOTIFICATION_COLLECTED_COOKIES_SHOWN,
    210                  content::Source<TabSpecificContentSettings>(content_settings));
    211   WebContentsModalDialogManager* web_contents_modal_dialog_manager =
    212       WebContentsModalDialogManager::FromWebContents(web_contents);
    213   WebContentsModalDialogManagerDelegate* modal_delegate =
    214       web_contents_modal_dialog_manager->delegate();
    215   DCHECK(modal_delegate);
    216   window_ = views::Widget::CreateWindowAsFramelessChild(
    217       this, modal_delegate->GetWebContentsModalDialogHost()->GetHostView());
    218   web_contents_modal_dialog_manager->ShowDialog(window_->GetNativeView());
    219 }
    220 
    221 ///////////////////////////////////////////////////////////////////////////////
    222 // CollectedCookiesViews, views::DialogDelegate implementation:
    223 
    224 base::string16 CollectedCookiesViews::GetWindowTitle() const {
    225   return l10n_util::GetStringUTF16(IDS_COLLECTED_COOKIES_DIALOG_TITLE);
    226 }
    227 
    228 int CollectedCookiesViews::GetDialogButtons() const {
    229   return ui::DIALOG_BUTTON_CANCEL;
    230 }
    231 
    232 base::string16 CollectedCookiesViews::GetDialogButtonLabel(
    233     ui::DialogButton button) const {
    234   return l10n_util::GetStringUTF16(IDS_CLOSE);
    235 }
    236 
    237 void CollectedCookiesViews::DeleteDelegate() {
    238   delete this;
    239 }
    240 
    241 bool CollectedCookiesViews::Cancel() {
    242   if (status_changed_) {
    243     CollectedCookiesInfoBarDelegate::Create(
    244         InfoBarService::FromWebContents(web_contents_));
    245   }
    246 
    247   return true;
    248 }
    249 
    250 // TODO(wittman): Remove this override once we move to the new style frame view
    251 // on all dialogs.
    252 views::NonClientFrameView* CollectedCookiesViews::CreateNonClientFrameView(
    253     views::Widget* widget) {
    254   return CreateConstrainedStyleNonClientFrameView(
    255       widget,
    256       web_contents_->GetBrowserContext());
    257 }
    258 
    259 ui::ModalType CollectedCookiesViews::GetModalType() const {
    260 #if defined(USE_ASH)
    261   return ui::MODAL_TYPE_CHILD;
    262 #else
    263   return views::WidgetDelegate::GetModalType();
    264 #endif
    265 }
    266 
    267 ///////////////////////////////////////////////////////////////////////////////
    268 // CollectedCookiesViews, views::ButtonListener implementation:
    269 
    270 void CollectedCookiesViews::ButtonPressed(views::Button* sender,
    271                                           const ui::Event& event) {
    272   if (sender == block_allowed_button_)
    273     AddContentException(allowed_cookies_tree_, CONTENT_SETTING_BLOCK);
    274   else if (sender == allow_blocked_button_)
    275     AddContentException(blocked_cookies_tree_, CONTENT_SETTING_ALLOW);
    276   else if (sender == for_session_blocked_button_)
    277     AddContentException(blocked_cookies_tree_, CONTENT_SETTING_SESSION_ONLY);
    278 }
    279 
    280 ///////////////////////////////////////////////////////////////////////////////
    281 // CollectedCookiesViews, views::TabbedPaneListener implementation:
    282 
    283 void CollectedCookiesViews::TabSelectedAt(int index) {
    284   EnableControls();
    285   ShowCookieInfo();
    286 }
    287 
    288 ///////////////////////////////////////////////////////////////////////////////
    289 // CollectedCookiesViews, views::TreeViewController implementation:
    290 
    291 void CollectedCookiesViews::OnTreeViewSelectionChanged(
    292     views::TreeView* tree_view) {
    293   EnableControls();
    294   ShowCookieInfo();
    295 }
    296 
    297 ///////////////////////////////////////////////////////////////////////////////
    298 // CollectedCookiesViews, views::View overrides:
    299 
    300 gfx::Size CollectedCookiesViews::GetMinimumSize() {
    301   // Allow UpdateWebContentsModalDialogPosition to clamp the dialog width.
    302   return gfx::Size(0, View::GetMinimumSize().height());
    303 }
    304 
    305 void CollectedCookiesViews::ViewHierarchyChanged(
    306     const ViewHierarchyChangedDetails& details) {
    307   if (details.is_add && details.child == this)
    308     Init();
    309 }
    310 
    311 ////////////////////////////////////////////////////////////////////////////////
    312 // CollectedCookiesViews, private:
    313 
    314 CollectedCookiesViews::~CollectedCookiesViews() {
    315   allowed_cookies_tree_->SetModel(NULL);
    316   blocked_cookies_tree_->SetModel(NULL);
    317 }
    318 
    319 void CollectedCookiesViews::Init() {
    320   using views::GridLayout;
    321 
    322   GridLayout* layout = GridLayout::CreatePanel(this);
    323   SetLayoutManager(layout);
    324 
    325   const int single_column_layout_id = 0;
    326   views::ColumnSet* column_set = layout->AddColumnSet(single_column_layout_id);
    327   column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 1,
    328                         GridLayout::USE_PREF, 0, 0);
    329 
    330   layout->StartRow(0, single_column_layout_id);
    331   views::TabbedPane* tabbed_pane = new views::TabbedPane();
    332   layout->SetInsets(gfx::Insets(kTabbedPaneTopPadding, 0, 0, 0));
    333 
    334   layout->AddView(tabbed_pane);
    335   // NOTE: Panes must be added after |tabbed_pane| has been added to its parent.
    336   base::string16 label_allowed = l10n_util::GetStringUTF16(
    337       IDS_COLLECTED_COOKIES_ALLOWED_COOKIES_TAB_LABEL);
    338   base::string16 label_blocked = l10n_util::GetStringUTF16(
    339       IDS_COLLECTED_COOKIES_BLOCKED_COOKIES_TAB_LABEL);
    340   tabbed_pane->AddTab(label_allowed, CreateAllowedPane());
    341   tabbed_pane->AddTab(label_blocked, CreateBlockedPane());
    342   tabbed_pane->SelectTabAt(0);
    343   tabbed_pane->set_listener(this);
    344   layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
    345 
    346   layout->StartRow(0, single_column_layout_id);
    347   cookie_info_view_ = new CookieInfoView();
    348   layout->AddView(cookie_info_view_);
    349   layout->AddPaddingRow(0, kCookieInfoBottomPadding);
    350 
    351   layout->StartRow(0, single_column_layout_id);
    352   infobar_ = new InfobarView();
    353   layout->AddView(infobar_);
    354 
    355   EnableControls();
    356   ShowCookieInfo();
    357 }
    358 
    359 views::View* CollectedCookiesViews::CreateAllowedPane() {
    360   TabSpecificContentSettings* content_settings =
    361       TabSpecificContentSettings::FromWebContents(web_contents_);
    362 
    363   // Create the controls that go into the pane.
    364   allowed_label_ = new views::Label(l10n_util::GetStringUTF16(
    365       IDS_COLLECTED_COOKIES_ALLOWED_COOKIES_LABEL));
    366 
    367   const LocalSharedObjectsContainer& allowed_data =
    368       content_settings->allowed_local_shared_objects();
    369   allowed_cookies_tree_model_ = allowed_data.CreateCookiesTreeModel();
    370   allowed_cookies_tree_ = new views::TreeView();
    371   allowed_cookies_tree_->SetModel(allowed_cookies_tree_model_.get());
    372   allowed_cookies_tree_->SetRootShown(false);
    373   allowed_cookies_tree_->SetEditable(false);
    374   allowed_cookies_tree_->set_auto_expand_children(true);
    375   allowed_cookies_tree_->SetController(this);
    376 
    377   block_allowed_button_ = new views::LabelButton(this,
    378       l10n_util::GetStringUTF16(IDS_COLLECTED_COOKIES_BLOCK_BUTTON));
    379   block_allowed_button_->SetStyle(views::Button::STYLE_NATIVE_TEXTBUTTON);
    380 
    381   // Create the view that holds all the controls together.  This will be the
    382   // pane added to the tabbed pane.
    383   using views::GridLayout;
    384 
    385   views::View* pane = new views::View();
    386   GridLayout* layout = GridLayout::CreatePanel(pane);
    387   layout->SetInsets(kVPanelPadding, views::kButtonHEdgeMarginNew,
    388                     kVPanelPadding, views::kButtonHEdgeMarginNew);
    389   pane->SetLayoutManager(layout);
    390 
    391   const int single_column_layout_id = 0;
    392   views::ColumnSet* column_set = layout->AddColumnSet(single_column_layout_id);
    393   column_set->AddColumn(GridLayout::LEADING, GridLayout::FILL, 1,
    394                         GridLayout::USE_PREF, 0, 0);
    395 
    396   layout->StartRow(0, single_column_layout_id);
    397   layout->AddView(allowed_label_);
    398   layout->AddPaddingRow(0, kLabelBottomPadding);
    399 
    400   layout->StartRow(1, single_column_layout_id);
    401   layout->AddView(CreateScrollView(allowed_cookies_tree_), 1, 1,
    402                   GridLayout::FILL, GridLayout::FILL, kTreeViewWidth,
    403                   kTreeViewHeight);
    404   layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
    405 
    406   layout->StartRow(0, single_column_layout_id);
    407   layout->AddView(block_allowed_button_, 1, 1, GridLayout::LEADING,
    408                   GridLayout::CENTER);
    409 
    410   return pane;
    411 }
    412 
    413 views::View* CollectedCookiesViews::CreateBlockedPane() {
    414   TabSpecificContentSettings* content_settings =
    415       TabSpecificContentSettings::FromWebContents(web_contents_);
    416 
    417   Profile* profile =
    418       Profile::FromBrowserContext(web_contents_->GetBrowserContext());
    419   PrefService* prefs = profile->GetPrefs();
    420 
    421   // Create the controls that go into the pane.
    422   blocked_label_ = new views::Label(
    423       l10n_util::GetStringUTF16(
    424           prefs->GetBoolean(prefs::kBlockThirdPartyCookies) ?
    425               IDS_COLLECTED_COOKIES_BLOCKED_THIRD_PARTY_BLOCKING_ENABLED :
    426               IDS_COLLECTED_COOKIES_BLOCKED_COOKIES_LABEL));
    427   blocked_label_->SetMultiLine(true);
    428   blocked_label_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
    429   const LocalSharedObjectsContainer& blocked_data =
    430       content_settings->blocked_local_shared_objects();
    431   blocked_cookies_tree_model_ = blocked_data.CreateCookiesTreeModel();
    432   blocked_cookies_tree_ = new views::TreeView();
    433   blocked_cookies_tree_->SetModel(blocked_cookies_tree_model_.get());
    434   blocked_cookies_tree_->SetRootShown(false);
    435   blocked_cookies_tree_->SetEditable(false);
    436   blocked_cookies_tree_->set_auto_expand_children(true);
    437   blocked_cookies_tree_->SetController(this);
    438 
    439   allow_blocked_button_ = new views::LabelButton(this,
    440       l10n_util::GetStringUTF16(IDS_COLLECTED_COOKIES_ALLOW_BUTTON));
    441   allow_blocked_button_->SetStyle(views::Button::STYLE_NATIVE_TEXTBUTTON);
    442   for_session_blocked_button_ = new views::LabelButton(this,
    443       l10n_util::GetStringUTF16(IDS_COLLECTED_COOKIES_SESSION_ONLY_BUTTON));
    444   for_session_blocked_button_->SetStyle(views::Button::STYLE_NATIVE_TEXTBUTTON);
    445 
    446   // Create the view that holds all the controls together.  This will be the
    447   // pane added to the tabbed pane.
    448   using views::GridLayout;
    449 
    450   views::View* pane = new views::View();
    451   GridLayout* layout = GridLayout::CreatePanel(pane);
    452   layout->SetInsets(kVPanelPadding, views::kButtonHEdgeMarginNew,
    453                     kVPanelPadding, views::kButtonHEdgeMarginNew);
    454   pane->SetLayoutManager(layout);
    455 
    456   const int single_column_layout_id = 0;
    457   views::ColumnSet* column_set = layout->AddColumnSet(single_column_layout_id);
    458   column_set->AddColumn(GridLayout::LEADING, GridLayout::FILL, 1,
    459                         GridLayout::USE_PREF, 0, 0);
    460 
    461   const int three_columns_layout_id = 1;
    462   column_set = layout->AddColumnSet(three_columns_layout_id);
    463   column_set->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 0,
    464                         GridLayout::USE_PREF, 0, 0);
    465   column_set->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing);
    466   column_set->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 0,
    467                         GridLayout::USE_PREF, 0, 0);
    468 
    469   layout->StartRow(0, single_column_layout_id);
    470   layout->AddView(blocked_label_, 1, 1, GridLayout::FILL, GridLayout::FILL);
    471   layout->AddPaddingRow(0, kLabelBottomPadding);
    472 
    473   layout->StartRow(1, single_column_layout_id);
    474   layout->AddView(
    475       CreateScrollView(blocked_cookies_tree_), 1, 1,
    476       GridLayout::FILL, GridLayout::FILL, kTreeViewWidth, kTreeViewHeight);
    477   layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
    478 
    479   layout->StartRow(0, three_columns_layout_id);
    480   layout->AddView(allow_blocked_button_);
    481   layout->AddView(for_session_blocked_button_);
    482 
    483   return pane;
    484 }
    485 
    486 views::View* CollectedCookiesViews::CreateScrollView(views::TreeView* pane) {
    487   views::ScrollView* scroll_view = new views::ScrollView();
    488   scroll_view->SetContents(pane);
    489   scroll_view->set_border(
    490       views::Border::CreateSolidBorder(1, kCookiesBorderColor));
    491   return scroll_view;
    492 }
    493 
    494 void CollectedCookiesViews::EnableControls() {
    495   bool enable_allowed_buttons = false;
    496   ui::TreeModelNode* node = allowed_cookies_tree_->GetSelectedNode();
    497   if (node) {
    498     CookieTreeNode* cookie_node = static_cast<CookieTreeNode*>(node);
    499     if (cookie_node->GetDetailedInfo().node_type ==
    500         CookieTreeNode::DetailedInfo::TYPE_HOST) {
    501       enable_allowed_buttons = static_cast<CookieTreeHostNode*>(
    502           cookie_node)->CanCreateContentException();
    503     }
    504   }
    505   block_allowed_button_->SetEnabled(enable_allowed_buttons);
    506 
    507   bool enable_blocked_buttons = false;
    508   node = blocked_cookies_tree_->GetSelectedNode();
    509   if (node) {
    510     CookieTreeNode* cookie_node = static_cast<CookieTreeNode*>(node);
    511     if (cookie_node->GetDetailedInfo().node_type ==
    512         CookieTreeNode::DetailedInfo::TYPE_HOST) {
    513       enable_blocked_buttons = static_cast<CookieTreeHostNode*>(
    514           cookie_node)->CanCreateContentException();
    515     }
    516   }
    517   allow_blocked_button_->SetEnabled(enable_blocked_buttons);
    518   for_session_blocked_button_->SetEnabled(enable_blocked_buttons);
    519 }
    520 
    521 void CollectedCookiesViews::ShowCookieInfo() {
    522   ui::TreeModelNode* node = allowed_cookies_tree_->GetSelectedNode();
    523   if (!node)
    524     node = blocked_cookies_tree_->GetSelectedNode();
    525 
    526   if (node) {
    527     CookieTreeNode* cookie_node = static_cast<CookieTreeNode*>(node);
    528     const CookieTreeNode::DetailedInfo detailed_info =
    529         cookie_node->GetDetailedInfo();
    530 
    531     if (detailed_info.node_type == CookieTreeNode::DetailedInfo::TYPE_COOKIE) {
    532       cookie_info_view_->SetCookie(detailed_info.cookie->Domain(),
    533                                    *detailed_info.cookie);
    534     } else {
    535       cookie_info_view_->ClearCookieDisplay();
    536     }
    537   } else {
    538     cookie_info_view_->ClearCookieDisplay();
    539   }
    540 }
    541 
    542 void CollectedCookiesViews::AddContentException(views::TreeView* tree_view,
    543                                                 ContentSetting setting) {
    544   CookieTreeHostNode* host_node =
    545       static_cast<CookieTreeHostNode*>(tree_view->GetSelectedNode());
    546   Profile* profile =
    547       Profile::FromBrowserContext(web_contents_->GetBrowserContext());
    548   host_node->CreateContentException(
    549       CookieSettings::Factory::GetForProfile(profile).get(), setting);
    550   infobar_->UpdateVisibility(true, setting, host_node->GetTitle());
    551   status_changed_ = true;
    552 }
    553 
    554 ///////////////////////////////////////////////////////////////////////////////
    555 // CollectedCookiesViews, content::NotificationObserver implementation:
    556 
    557 void CollectedCookiesViews::Observe(
    558     int type,
    559     const content::NotificationSource& source,
    560     const content::NotificationDetails& details) {
    561   DCHECK_EQ(chrome::NOTIFICATION_COLLECTED_COOKIES_SHOWN, type);
    562   window_->Close();
    563 }
    564