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