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