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