• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2011 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_win.h"
6 
7 #include "chrome/browser/cookies_tree_model.h"
8 #include "chrome/browser/profiles/profile.h"
9 #include "chrome/browser/ui/collected_cookies_infobar_delegate.h"
10 #include "chrome/browser/ui/views/cookie_info_view.h"
11 #include "content/browser/tab_contents/tab_contents.h"
12 #include "content/common/notification_details.h"
13 #include "content/common/notification_source.h"
14 #include "grit/generated_resources.h"
15 #include "grit/locale_settings.h"
16 #include "grit/theme_resources.h"
17 #include "ui/base/l10n/l10n_util.h"
18 #include "ui/base/resource/resource_bundle.h"
19 #include "ui/gfx/color_utils.h"
20 #include "views/controls/button/native_button.h"
21 #include "views/controls/image_view.h"
22 #include "views/controls/label.h"
23 #include "views/controls/separator.h"
24 #include "views/controls/tabbed_pane/tabbed_pane.h"
25 #include "views/layout/box_layout.h"
26 #include "views/layout/grid_layout.h"
27 #include "views/layout/layout_constants.h"
28 #include "views/widget/root_view.h"
29 #include "views/widget/widget_win.h"
30 #include "views/window/window.h"
31 
32 namespace browser {
33 
34 // Declared in browser_dialogs.h so others don't have to depend on our header.
ShowCollectedCookiesDialog(gfx::NativeWindow parent_window,TabContents * tab_contents)35 void ShowCollectedCookiesDialog(gfx::NativeWindow parent_window,
36                                 TabContents* tab_contents) {
37   // Deletes itself on close.
38   new CollectedCookiesWin(parent_window, tab_contents);
39 }
40 
41 }  // namespace browser
42 
43 namespace {
44 // Spacing between the infobar frame and its contents.
45 const int kInfobarVerticalPadding = 3;
46 const int kInfobarHorizontalPadding = 8;
47 
48 // Width of the infobar frame.
49 const int kInfobarBorderSize = 1;
50 
51 // Dimensions of the tree views.
52 const int kTreeViewWidth = 400;
53 const int kTreeViewHeight = 125;
54 
55 }  // namespace
56 
57 // A custom view that conditionally displays an infobar.
58 class InfobarView : public views::View {
59  public:
InfobarView()60   InfobarView() {
61     content_ = new views::View;
62     SkColor border_color = color_utils::GetSysSkColor(COLOR_3DSHADOW);
63     views::Border* border = views::Border::CreateSolidBorder(
64         kInfobarBorderSize, border_color);
65     content_->set_border(border);
66 
67     ResourceBundle& rb = ResourceBundle::GetSharedInstance();
68     info_image_ = new views::ImageView();
69     info_image_->SetImage(rb.GetBitmapNamed(IDR_INFO));
70     label_ = new views::Label();
71   }
~InfobarView()72   virtual ~InfobarView() {}
73 
74   // Update the visibility of the infobar. If |is_visible| is true, a rule for
75   // |setting| on |domain_name| was created.
UpdateVisibility(bool is_visible,ContentSetting setting,const std::wstring & domain_name)76   void UpdateVisibility(bool is_visible,
77                         ContentSetting setting,
78                         const std::wstring& domain_name) {
79     if (!is_visible) {
80       SetVisible(false);
81       return;
82     }
83 
84     std::wstring label;
85     switch (setting) {
86       case CONTENT_SETTING_BLOCK:
87         label = UTF16ToWide(l10n_util::GetStringFUTF16(
88             IDS_COLLECTED_COOKIES_BLOCK_RULE_CREATED,
89             WideToUTF16(domain_name)));
90         break;
91 
92       case CONTENT_SETTING_ALLOW:
93         label = UTF16ToWide(l10n_util::GetStringFUTF16(
94             IDS_COLLECTED_COOKIES_ALLOW_RULE_CREATED,
95             WideToUTF16(domain_name)));
96         break;
97 
98       case CONTENT_SETTING_SESSION_ONLY:
99         label = UTF16ToWide(l10n_util::GetStringFUTF16(
100             IDS_COLLECTED_COOKIES_SESSION_RULE_CREATED,
101             WideToUTF16(domain_name)));
102         break;
103 
104       default:
105         NOTREACHED();
106     }
107     label_->SetText(label);
108     content_->Layout();
109     SetVisible(true);
110   }
111 
112  private:
113   // Initialize contents and layout.
Init()114   void Init() {
115     AddChildView(content_);
116     content_->SetLayoutManager(
117         new views::BoxLayout(views::BoxLayout::kHorizontal,
118                              kInfobarHorizontalPadding,
119                              kInfobarVerticalPadding,
120                              views::kRelatedControlSmallHorizontalSpacing));
121     content_->AddChildView(info_image_);
122     content_->AddChildView(label_);
123     UpdateVisibility(false, CONTENT_SETTING_BLOCK, std::wstring());
124   }
125 
126   // views::View overrides.
GetPreferredSize()127   virtual gfx::Size GetPreferredSize() {
128     if (!IsVisible())
129       return gfx::Size();
130 
131     // Add space around the banner.
132     gfx::Size size(content_->GetPreferredSize());
133     size.Enlarge(0, 2 * views::kRelatedControlVerticalSpacing);
134     return size;
135   }
136 
Layout()137   virtual void Layout() {
138     content_->SetBounds(
139         0, views::kRelatedControlVerticalSpacing,
140         width(), height() - views::kRelatedControlVerticalSpacing);
141   }
142 
ViewHierarchyChanged(bool is_add,views::View * parent,views::View * child)143   virtual void ViewHierarchyChanged(bool is_add,
144                                     views::View* parent,
145                                     views::View* child) {
146     if (is_add && child == this)
147       Init();
148   }
149 
150   // Holds the info icon image and text label and renders the border.
151   views::View* content_;
152   // Info icon image.
153   views::ImageView* info_image_;
154   // The label responsible for rendering the text.
155   views::Label* label_;
156 
157   DISALLOW_COPY_AND_ASSIGN(InfobarView);
158 };
159 
160 ///////////////////////////////////////////////////////////////////////////////
161 // CollectedCookiesWin, constructor and destructor:
162 
CollectedCookiesWin(gfx::NativeWindow parent_window,TabContents * tab_contents)163 CollectedCookiesWin::CollectedCookiesWin(gfx::NativeWindow parent_window,
164                                          TabContents* tab_contents)
165     : tab_contents_(tab_contents),
166       allowed_label_(NULL),
167       blocked_label_(NULL),
168       allowed_cookies_tree_(NULL),
169       blocked_cookies_tree_(NULL),
170       block_allowed_button_(NULL),
171       allow_blocked_button_(NULL),
172       for_session_blocked_button_(NULL),
173       infobar_(NULL),
174       status_changed_(false) {
175   TabSpecificContentSettings* content_settings =
176       tab_contents->GetTabSpecificContentSettings();
177   registrar_.Add(this, NotificationType::COLLECTED_COOKIES_SHOWN,
178                  Source<TabSpecificContentSettings>(content_settings));
179 
180   Init();
181 
182   window_ = tab_contents_->CreateConstrainedDialog(this);
183 }
184 
~CollectedCookiesWin()185 CollectedCookiesWin::~CollectedCookiesWin() {
186   allowed_cookies_tree_->SetModel(NULL);
187   blocked_cookies_tree_->SetModel(NULL);
188 }
189 
Init()190 void CollectedCookiesWin::Init() {
191   using views::GridLayout;
192 
193   GridLayout* layout = GridLayout::CreatePanel(this);
194   SetLayoutManager(layout);
195 
196   const int single_column_layout_id = 0;
197   views::ColumnSet* column_set = layout->AddColumnSet(single_column_layout_id);
198   column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 1,
199                         GridLayout::USE_PREF, 0, 0);
200 
201   const int single_column_with_padding_layout_id = 1;
202   views::ColumnSet* column_set_with_padding = layout->AddColumnSet(
203       single_column_with_padding_layout_id);
204   column_set_with_padding->AddColumn(GridLayout::FILL, GridLayout::FILL, 1,
205                                      GridLayout::USE_PREF, 0, 0);
206   column_set_with_padding->AddPaddingColumn(0, 2);
207 
208   layout->StartRow(0, single_column_layout_id);
209   views::TabbedPane* tabbed_pane = new views::TabbedPane();
210   layout->AddView(tabbed_pane);
211   // NOTE: the panes need to be added after the tabbed_pane has been added to
212   // its parent.
213   std::wstring label_allowed = UTF16ToWide(l10n_util::GetStringUTF16(
214       IDS_COLLECTED_COOKIES_ALLOWED_COOKIES_TAB_LABEL));
215   std::wstring label_blocked = UTF16ToWide(l10n_util::GetStringUTF16(
216       IDS_COLLECTED_COOKIES_BLOCKED_COOKIES_TAB_LABEL));
217   tabbed_pane->AddTab(label_allowed, CreateAllowedPane());
218   tabbed_pane->AddTab(label_blocked, CreateBlockedPane());
219   tabbed_pane->SelectTabAt(0);
220   tabbed_pane->set_listener(this);
221   layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
222 
223   layout->StartRow(0, single_column_with_padding_layout_id);
224   cookie_info_view_ = new CookieInfoView(false);
225   layout->AddView(cookie_info_view_);
226   layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
227 
228   layout->StartRow(0, single_column_with_padding_layout_id);
229   infobar_ = new InfobarView();
230   layout->AddView(infobar_);
231 
232   EnableControls();
233   ShowCookieInfo();
234 }
235 
CreateAllowedPane()236 views::View* CollectedCookiesWin::CreateAllowedPane() {
237   TabSpecificContentSettings* content_settings =
238       tab_contents_->GetTabSpecificContentSettings();
239 
240   // Create the controls that go into the pane.
241   allowed_label_ = new views::Label(UTF16ToWide(l10n_util::GetStringUTF16(
242       IDS_COLLECTED_COOKIES_ALLOWED_COOKIES_LABEL)));
243   allowed_cookies_tree_model_.reset(
244       content_settings->GetAllowedCookiesTreeModel());
245   allowed_cookies_tree_ = new views::TreeView();
246   allowed_cookies_tree_->SetModel(allowed_cookies_tree_model_.get());
247   allowed_cookies_tree_->SetController(this);
248   allowed_cookies_tree_->SetRootShown(false);
249   allowed_cookies_tree_->SetEditable(false);
250   allowed_cookies_tree_->set_lines_at_root(true);
251   allowed_cookies_tree_->set_auto_expand_children(true);
252 
253   block_allowed_button_ = new views::NativeButton(this, UTF16ToWide(
254       l10n_util::GetStringUTF16(IDS_COLLECTED_COOKIES_BLOCK_BUTTON)));
255 
256   // Create the view that holds all the controls together.  This will be the
257   // pane added to the tabbed pane.
258   using views::GridLayout;
259 
260   views::View* pane = new views::View();
261   GridLayout* layout = GridLayout::CreatePanel(pane);
262   pane->SetLayoutManager(layout);
263 
264   const int single_column_layout_id = 0;
265   views::ColumnSet* column_set = layout->AddColumnSet(single_column_layout_id);
266   column_set->AddColumn(GridLayout::LEADING, GridLayout::FILL, 1,
267                         GridLayout::USE_PREF, 0, 0);
268 
269   layout->StartRow(0, single_column_layout_id);
270   layout->AddView(allowed_label_);
271   layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
272 
273   layout->StartRow(1, single_column_layout_id);
274   layout->AddView(allowed_cookies_tree_, 1, 1, GridLayout::FILL,
275                   GridLayout::FILL, kTreeViewWidth, kTreeViewHeight);
276   layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
277 
278   layout->StartRow(0, single_column_layout_id);
279   layout->AddView(block_allowed_button_, 1, 1, GridLayout::LEADING,
280                   GridLayout::CENTER);
281 
282   return pane;
283 }
284 
CreateBlockedPane()285 views::View* CollectedCookiesWin::CreateBlockedPane() {
286   TabSpecificContentSettings* content_settings =
287       tab_contents_->GetTabSpecificContentSettings();
288 
289   HostContentSettingsMap* host_content_settings_map =
290       tab_contents_->profile()->GetHostContentSettingsMap();
291 
292   // Create the controls that go into the pane.
293   blocked_label_ = new views::Label(
294       UTF16ToWide(l10n_util::GetStringUTF16(
295           host_content_settings_map->BlockThirdPartyCookies() ?
296               IDS_COLLECTED_COOKIES_BLOCKED_THIRD_PARTY_BLOCKING_ENABLED :
297               IDS_COLLECTED_COOKIES_BLOCKED_COOKIES_LABEL)));
298   blocked_label_->SetMultiLine(true);
299   blocked_label_->SetHorizontalAlignment(views::Label::ALIGN_LEFT);
300   blocked_cookies_tree_model_.reset(
301       content_settings->GetBlockedCookiesTreeModel());
302   blocked_cookies_tree_ = new views::TreeView();
303   blocked_cookies_tree_->SetModel(blocked_cookies_tree_model_.get());
304   blocked_cookies_tree_->SetController(this);
305   blocked_cookies_tree_->SetRootShown(false);
306   blocked_cookies_tree_->SetEditable(false);
307   blocked_cookies_tree_->set_lines_at_root(true);
308   blocked_cookies_tree_->set_auto_expand_children(true);
309 
310   allow_blocked_button_ = new views::NativeButton(this, UTF16ToWide(
311       l10n_util::GetStringUTF16(IDS_COLLECTED_COOKIES_ALLOW_BUTTON)));
312   for_session_blocked_button_ = new views::NativeButton(this, UTF16ToWide(
313       l10n_util::GetStringUTF16(IDS_COLLECTED_COOKIES_SESSION_ONLY_BUTTON)));
314 
315   // Create the view that holds all the controls together.  This will be the
316   // pane added to the tabbed pane.
317   using views::GridLayout;
318 
319   views::View* pane = new views::View();
320   GridLayout* layout = GridLayout::CreatePanel(pane);
321   pane->SetLayoutManager(layout);
322 
323   const int single_column_layout_id = 0;
324   views::ColumnSet* column_set = layout->AddColumnSet(single_column_layout_id);
325   column_set->AddColumn(GridLayout::LEADING, GridLayout::FILL, 1,
326                         GridLayout::USE_PREF, 0, 0);
327 
328   const int three_columns_layout_id = 1;
329   column_set = layout->AddColumnSet(three_columns_layout_id);
330   column_set->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 0,
331                         GridLayout::USE_PREF, 0, 0);
332   column_set->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing);
333   column_set->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 0,
334                         GridLayout::USE_PREF, 0, 0);
335 
336   layout->StartRow(0, single_column_layout_id);
337   layout->AddView(blocked_label_, 1, 1, GridLayout::FILL, GridLayout::FILL);
338   layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
339 
340   layout->StartRow(1, single_column_layout_id);
341   layout->AddView(
342       blocked_cookies_tree_, 1, 1, GridLayout::FILL, GridLayout::FILL,
343       kTreeViewWidth, kTreeViewHeight);
344   layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing);
345 
346   layout->StartRow(0, three_columns_layout_id);
347   layout->AddView(allow_blocked_button_);
348   layout->AddView(for_session_blocked_button_);
349 
350   return pane;
351 }
352 
353 ///////////////////////////////////////////////////////////////////////////////
354 // ConstrainedDialogDelegate implementation.
355 
GetWindowTitle() const356 std::wstring CollectedCookiesWin::GetWindowTitle() const {
357   return UTF16ToWide(
358       l10n_util::GetStringUTF16(IDS_COLLECTED_COOKIES_DIALOG_TITLE));
359 }
360 
GetDialogButtons() const361 int CollectedCookiesWin::GetDialogButtons() const {
362   return MessageBoxFlags::DIALOGBUTTON_CANCEL;
363 }
364 
GetDialogButtonLabel(MessageBoxFlags::DialogButton button) const365 std::wstring CollectedCookiesWin::GetDialogButtonLabel(
366     MessageBoxFlags::DialogButton button) const {
367   return UTF16ToWide(l10n_util::GetStringUTF16(IDS_CLOSE));
368 }
369 
DeleteDelegate()370 void CollectedCookiesWin::DeleteDelegate() {
371   delete this;
372 }
373 
Cancel()374 bool CollectedCookiesWin::Cancel() {
375   if (status_changed_) {
376     tab_contents_->AddInfoBar(
377         new CollectedCookiesInfoBarDelegate(tab_contents_));
378   }
379 
380   return true;
381 }
382 
GetContentsView()383 views::View* CollectedCookiesWin::GetContentsView() {
384   return this;
385 }
386 
387 ///////////////////////////////////////////////////////////////////////////////
388 // views::ButtonListener implementation.
389 
ButtonPressed(views::Button * sender,const views::Event & event)390 void CollectedCookiesWin::ButtonPressed(views::Button* sender,
391                                         const views::Event& event) {
392   if (sender == block_allowed_button_)
393     AddContentException(allowed_cookies_tree_, CONTENT_SETTING_BLOCK);
394   else if (sender == allow_blocked_button_)
395     AddContentException(blocked_cookies_tree_, CONTENT_SETTING_ALLOW);
396   else if (sender == for_session_blocked_button_)
397     AddContentException(blocked_cookies_tree_, CONTENT_SETTING_SESSION_ONLY);
398 }
399 
400 ///////////////////////////////////////////////////////////////////////////////
401 // views::TabbedPaneListener implementation.
402 
TabSelectedAt(int index)403 void CollectedCookiesWin::TabSelectedAt(int index) {
404   EnableControls();
405   ShowCookieInfo();
406 }
407 
408 ///////////////////////////////////////////////////////////////////////////////
409 // views::TreeViewController implementation.
410 
OnTreeViewSelectionChanged(views::TreeView * tree_view)411 void CollectedCookiesWin::OnTreeViewSelectionChanged(
412     views::TreeView* tree_view) {
413   EnableControls();
414   ShowCookieInfo();
415 }
416 
417 ///////////////////////////////////////////////////////////////////////////////
418 // CollectedCookiesWin, private methods.
419 
EnableControls()420 void CollectedCookiesWin::EnableControls() {
421   bool enable_allowed_buttons = false;
422   ui::TreeModelNode* node = allowed_cookies_tree_->GetSelectedNode();
423   if (node) {
424     CookieTreeNode* cookie_node = static_cast<CookieTreeNode*>(node);
425     if (cookie_node->GetDetailedInfo().node_type ==
426         CookieTreeNode::DetailedInfo::TYPE_ORIGIN) {
427       enable_allowed_buttons = static_cast<CookieTreeOriginNode*>(
428           cookie_node)->CanCreateContentException();
429     }
430   }
431   block_allowed_button_->SetEnabled(enable_allowed_buttons);
432 
433   bool enable_blocked_buttons = false;
434   node = blocked_cookies_tree_->GetSelectedNode();
435   if (node) {
436     CookieTreeNode* cookie_node = static_cast<CookieTreeNode*>(node);
437     if (cookie_node->GetDetailedInfo().node_type ==
438         CookieTreeNode::DetailedInfo::TYPE_ORIGIN) {
439       enable_blocked_buttons = static_cast<CookieTreeOriginNode*>(
440           cookie_node)->CanCreateContentException();
441     }
442   }
443   allow_blocked_button_->SetEnabled(enable_blocked_buttons);
444   for_session_blocked_button_->SetEnabled(enable_blocked_buttons);
445 }
446 
ShowCookieInfo()447 void CollectedCookiesWin::ShowCookieInfo() {
448   ui::TreeModelNode* node = allowed_cookies_tree_->GetSelectedNode();
449   if (!node)
450     node = blocked_cookies_tree_->GetSelectedNode();
451 
452   if (node) {
453     CookieTreeNode* cookie_node = static_cast<CookieTreeNode*>(node);
454     const CookieTreeNode::DetailedInfo detailed_info =
455         cookie_node->GetDetailedInfo();
456 
457     if (detailed_info.node_type == CookieTreeNode::DetailedInfo::TYPE_COOKIE) {
458       CookieTreeCookieNode* cookie_info_node =
459           static_cast<CookieTreeCookieNode*>(cookie_node);
460       cookie_info_view_->SetCookie(detailed_info.cookie->Domain(),
461                                    *detailed_info.cookie);
462     } else {
463       cookie_info_view_->ClearCookieDisplay();
464     }
465   } else {
466     cookie_info_view_->ClearCookieDisplay();
467   }
468 }
469 
AddContentException(views::TreeView * tree_view,ContentSetting setting)470 void CollectedCookiesWin::AddContentException(views::TreeView* tree_view,
471                                               ContentSetting setting) {
472   CookieTreeOriginNode* origin_node =
473       static_cast<CookieTreeOriginNode*>(tree_view->GetSelectedNode());
474   origin_node->CreateContentException(
475       tab_contents_->profile()->GetHostContentSettingsMap(), setting);
476   infobar_->UpdateVisibility(true, setting, origin_node->GetTitle());
477   gfx::Rect bounds = GetWidget()->GetClientAreaScreenBounds();
478   // WidgetWin::GetBounds returns the bounds relative to the parent window,
479   // while WidgetWin::SetBounds wants screen coordinates. Do the translation
480   // here until http://crbug.com/52851 is fixed.
481   POINT topleft = {bounds.x(), bounds.y()};
482   MapWindowPoints(HWND_DESKTOP, tab_contents_->GetNativeView(), &topleft, 1);
483   gfx::Size size = GetRootView()->GetPreferredSize();
484   bounds.SetRect(topleft.x, topleft.y, size.width(), size.height());
485   GetWidget()->SetBounds(bounds);
486   status_changed_ = true;
487 }
488 
489 ///////////////////////////////////////////////////////////////////////////////
490 // NotificationObserver implementation.
491 
Observe(NotificationType type,const NotificationSource & source,const NotificationDetails & details)492 void CollectedCookiesWin::Observe(NotificationType type,
493                                    const NotificationSource& source,
494                                    const NotificationDetails& details) {
495   DCHECK(type == NotificationType::COLLECTED_COOKIES_SHOWN);
496   DCHECK_EQ(Source<TabSpecificContentSettings>(source).ptr(),
497             tab_contents_->GetTabSpecificContentSettings());
498   window_->CloseConstrainedWindow();
499 }
500