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.
5 #include "chrome/browser/ui/views/collected_cookies_views.h"
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/cookie_info_view.h"
24 #include "chrome/common/pref_names.h"
25 #include "components/web_modal/web_contents_modal_dialog_host.h"
26 #include "components/web_modal/web_contents_modal_dialog_manager.h"
27 #include "components/web_modal/web_contents_modal_dialog_manager_delegate.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/generated_resources.h"
32 #include "grit/locale_settings.h"
33 #include "grit/theme_resources.h"
34 #include "net/cookies/canonical_cookie.h"
35 #include "ui/base/l10n/l10n_util.h"
36 #include "ui/base/resource/resource_bundle.h"
37 #include "ui/gfx/color_utils.h"
38 #include "ui/views/border.h"
39 #include "ui/views/controls/button/label_button.h"
40 #include "ui/views/controls/image_view.h"
41 #include "ui/views/controls/label.h"
42 #include "ui/views/controls/scroll_view.h"
43 #include "ui/views/controls/tabbed_pane/tabbed_pane.h"
44 #include "ui/views/controls/tree/tree_view.h"
45 #include "ui/views/layout/box_layout.h"
46 #include "ui/views/layout/grid_layout.h"
47 #include "ui/views/layout/layout_constants.h"
48 #include "ui/views/widget/widget.h"
49 #include "ui/views/window/dialog_delegate.h"
51 using web_modal::WebContentsModalDialogManager
;
52 using web_modal::WebContentsModalDialogManagerDelegate
;
56 // Declared in browser_dialogs.h so others don't have to depend on our header.
57 void ShowCollectedCookiesDialog(content::WebContents
* web_contents
) {
58 // Deletes itself on close.
59 new CollectedCookiesViews(web_contents
);
66 // Spacing between the infobar frame and its contents.
67 const int kInfobarVerticalPadding
= 3;
68 const int kInfobarHorizontalPadding
= 8;
70 // Width of the infobar frame.
71 const int kInfobarBorderSize
= 1;
73 // Dimensions of the tree views.
74 const int kTreeViewWidth
= 400;
75 const int kTreeViewHeight
= 125;
77 // The color of the border around the cookies tree view.
78 const SkColor kCookiesBorderColor
= SkColorSetRGB(0xC8, 0xC8, 0xC8);
80 // Spacing constants used with the new dialog style.
81 const int kTabbedPaneTopPadding
= 14;
82 const int kLabelBottomPadding
= 17;
83 const int kCookieInfoBottomPadding
= 4;
84 const int kVPanelPadding
= 15;
88 // A custom view that conditionally displays an infobar.
89 class InfobarView
: public views::View
{
92 content_
= new views::View
;
93 #if defined(USE_AURA) || !defined(OS_WIN)
94 SkColor border_color
= SK_ColorGRAY
;
96 SkColor border_color
= color_utils::GetSysSkColor(COLOR_3DSHADOW
);
99 views::Border::CreateSolidBorder(kInfobarBorderSize
, border_color
));
101 ui::ResourceBundle
& rb
= ui::ResourceBundle::GetSharedInstance();
102 info_image_
= new views::ImageView();
103 info_image_
->SetImage(rb
.GetImageSkiaNamed(IDR_INFO
));
104 label_
= new views::Label();
106 virtual ~InfobarView() {}
108 // Update the visibility of the infobar. If |is_visible| is true, a rule for
109 // |setting| on |domain_name| was created.
110 void UpdateVisibility(bool is_visible
,
111 ContentSetting setting
,
112 const base::string16
& domain_name
) {
118 base::string16 label
;
120 case CONTENT_SETTING_BLOCK
:
121 label
= l10n_util::GetStringFUTF16(
122 IDS_COLLECTED_COOKIES_BLOCK_RULE_CREATED
, domain_name
);
125 case CONTENT_SETTING_ALLOW
:
126 label
= l10n_util::GetStringFUTF16(
127 IDS_COLLECTED_COOKIES_ALLOW_RULE_CREATED
, domain_name
);
130 case CONTENT_SETTING_SESSION_ONLY
:
131 label
= l10n_util::GetStringFUTF16(
132 IDS_COLLECTED_COOKIES_SESSION_RULE_CREATED
, domain_name
);
138 label_
->SetText(label
);
144 // Initialize contents and layout.
146 AddChildView(content_
);
147 content_
->SetLayoutManager(
148 new views::BoxLayout(views::BoxLayout::kHorizontal
,
149 kInfobarHorizontalPadding
,
150 kInfobarVerticalPadding
,
151 views::kRelatedControlSmallHorizontalSpacing
));
152 content_
->AddChildView(info_image_
);
153 content_
->AddChildView(label_
);
154 UpdateVisibility(false, CONTENT_SETTING_BLOCK
, base::string16());
157 // views::View overrides.
158 virtual gfx::Size
GetPreferredSize() OVERRIDE
{
162 // Add space around the banner.
163 gfx::Size
size(content_
->GetPreferredSize());
164 size
.Enlarge(0, 2 * views::kRelatedControlVerticalSpacing
);
168 virtual void Layout() OVERRIDE
{
170 0, views::kRelatedControlVerticalSpacing
,
171 width(), height() - views::kRelatedControlVerticalSpacing
);
174 virtual void ViewHierarchyChanged(
175 const ViewHierarchyChangedDetails
& details
) OVERRIDE
{
176 if (details
.is_add
&& details
.child
== this)
180 // Holds the info icon image and text label and renders the border.
181 views::View
* content_
;
183 views::ImageView
* info_image_
;
184 // The label responsible for rendering the text.
185 views::Label
* label_
;
187 DISALLOW_COPY_AND_ASSIGN(InfobarView
);
190 ///////////////////////////////////////////////////////////////////////////////
191 // CollectedCookiesViews, public:
193 CollectedCookiesViews::CollectedCookiesViews(content::WebContents
* web_contents
)
194 : web_contents_(web_contents
),
195 allowed_label_(NULL
),
196 blocked_label_(NULL
),
197 allowed_cookies_tree_(NULL
),
198 blocked_cookies_tree_(NULL
),
199 block_allowed_button_(NULL
),
200 delete_allowed_button_(NULL
),
201 allow_blocked_button_(NULL
),
202 for_session_blocked_button_(NULL
),
203 cookie_info_view_(NULL
),
205 status_changed_(false) {
206 TabSpecificContentSettings
* content_settings
=
207 TabSpecificContentSettings::FromWebContents(web_contents
);
208 registrar_
.Add(this, chrome::NOTIFICATION_COLLECTED_COOKIES_SHOWN
,
209 content::Source
<TabSpecificContentSettings
>(content_settings
));
210 WebContentsModalDialogManager
* web_contents_modal_dialog_manager
=
211 WebContentsModalDialogManager::FromWebContents(web_contents
);
212 WebContentsModalDialogManagerDelegate
* modal_delegate
=
213 web_contents_modal_dialog_manager
->delegate();
214 DCHECK(modal_delegate
);
215 window_
= views::Widget::CreateWindowAsFramelessChild(
216 this, modal_delegate
->GetWebContentsModalDialogHost()->GetHostView());
217 web_contents_modal_dialog_manager
->ShowDialog(window_
->GetNativeView());
220 ///////////////////////////////////////////////////////////////////////////////
221 // CollectedCookiesViews, views::DialogDelegate implementation:
223 base::string16
CollectedCookiesViews::GetWindowTitle() const {
224 return l10n_util::GetStringUTF16(IDS_COLLECTED_COOKIES_DIALOG_TITLE
);
227 int CollectedCookiesViews::GetDialogButtons() const {
228 return ui::DIALOG_BUTTON_CANCEL
;
231 base::string16
CollectedCookiesViews::GetDialogButtonLabel(
232 ui::DialogButton button
) const {
233 return l10n_util::GetStringUTF16(IDS_CLOSE
);
236 void CollectedCookiesViews::DeleteDelegate() {
240 bool CollectedCookiesViews::Cancel() {
241 if (status_changed_
) {
242 CollectedCookiesInfoBarDelegate::Create(
243 InfoBarService::FromWebContents(web_contents_
));
249 ui::ModalType
CollectedCookiesViews::GetModalType() const {
251 return ui::MODAL_TYPE_CHILD
;
253 return views::WidgetDelegate::GetModalType();
257 ///////////////////////////////////////////////////////////////////////////////
258 // CollectedCookiesViews, views::ButtonListener implementation:
260 void CollectedCookiesViews::ButtonPressed(views::Button
* sender
,
261 const ui::Event
& event
) {
262 if (sender
== block_allowed_button_
) {
263 AddContentException(allowed_cookies_tree_
, CONTENT_SETTING_BLOCK
);
264 } else if (sender
== delete_allowed_button_
) {
265 allowed_cookies_tree_model_
->DeleteCookieNode(
266 static_cast<CookieTreeNode
*>(allowed_cookies_tree_
->GetSelectedNode()));
267 } else if (sender
== allow_blocked_button_
) {
268 AddContentException(blocked_cookies_tree_
, CONTENT_SETTING_ALLOW
);
269 } else if (sender
== for_session_blocked_button_
) {
270 AddContentException(blocked_cookies_tree_
, CONTENT_SETTING_SESSION_ONLY
);
274 ///////////////////////////////////////////////////////////////////////////////
275 // CollectedCookiesViews, views::TabbedPaneListener implementation:
277 void CollectedCookiesViews::TabSelectedAt(int index
) {
282 ///////////////////////////////////////////////////////////////////////////////
283 // CollectedCookiesViews, views::TreeViewController implementation:
285 void CollectedCookiesViews::OnTreeViewSelectionChanged(
286 views::TreeView
* tree_view
) {
291 ///////////////////////////////////////////////////////////////////////////////
292 // CollectedCookiesViews, views::View overrides:
294 gfx::Size
CollectedCookiesViews::GetMinimumSize() {
295 // Allow UpdateWebContentsModalDialogPosition to clamp the dialog width.
296 return gfx::Size(0, View::GetMinimumSize().height());
299 void CollectedCookiesViews::ViewHierarchyChanged(
300 const ViewHierarchyChangedDetails
& details
) {
301 if (details
.is_add
&& details
.child
== this)
305 ////////////////////////////////////////////////////////////////////////////////
306 // CollectedCookiesViews, private:
308 CollectedCookiesViews::~CollectedCookiesViews() {
309 allowed_cookies_tree_
->SetModel(NULL
);
310 blocked_cookies_tree_
->SetModel(NULL
);
313 void CollectedCookiesViews::Init() {
314 using views::GridLayout
;
316 GridLayout
* layout
= GridLayout::CreatePanel(this);
317 SetLayoutManager(layout
);
319 const int single_column_layout_id
= 0;
320 views::ColumnSet
* column_set
= layout
->AddColumnSet(single_column_layout_id
);
321 column_set
->AddColumn(GridLayout::FILL
, GridLayout::FILL
, 1,
322 GridLayout::USE_PREF
, 0, 0);
324 layout
->StartRow(0, single_column_layout_id
);
325 views::TabbedPane
* tabbed_pane
= new views::TabbedPane();
326 layout
->SetInsets(gfx::Insets(kTabbedPaneTopPadding
, 0, 0, 0));
328 layout
->AddView(tabbed_pane
);
329 // NOTE: Panes must be added after |tabbed_pane| has been added to its parent.
330 base::string16 label_allowed
= l10n_util::GetStringUTF16(
331 IDS_COLLECTED_COOKIES_ALLOWED_COOKIES_TAB_LABEL
);
332 base::string16 label_blocked
= l10n_util::GetStringUTF16(
333 IDS_COLLECTED_COOKIES_BLOCKED_COOKIES_TAB_LABEL
);
334 tabbed_pane
->AddTab(label_allowed
, CreateAllowedPane());
335 tabbed_pane
->AddTab(label_blocked
, CreateBlockedPane());
336 tabbed_pane
->SelectTabAt(0);
337 tabbed_pane
->set_listener(this);
338 layout
->AddPaddingRow(0, views::kRelatedControlVerticalSpacing
);
340 layout
->StartRow(0, single_column_layout_id
);
341 cookie_info_view_
= new CookieInfoView();
342 layout
->AddView(cookie_info_view_
);
343 layout
->AddPaddingRow(0, kCookieInfoBottomPadding
);
345 layout
->StartRow(0, single_column_layout_id
);
346 infobar_
= new InfobarView();
347 layout
->AddView(infobar_
);
353 views::View
* CollectedCookiesViews::CreateAllowedPane() {
354 TabSpecificContentSettings
* content_settings
=
355 TabSpecificContentSettings::FromWebContents(web_contents_
);
357 // Create the controls that go into the pane.
358 allowed_label_
= new views::Label(l10n_util::GetStringUTF16(
359 IDS_COLLECTED_COOKIES_ALLOWED_COOKIES_LABEL
));
361 const LocalSharedObjectsContainer
& allowed_data
=
362 content_settings
->allowed_local_shared_objects();
363 allowed_cookies_tree_model_
= allowed_data
.CreateCookiesTreeModel();
364 allowed_cookies_tree_
= new views::TreeView();
365 allowed_cookies_tree_
->SetModel(allowed_cookies_tree_model_
.get());
366 allowed_cookies_tree_
->SetRootShown(false);
367 allowed_cookies_tree_
->SetEditable(false);
368 allowed_cookies_tree_
->set_auto_expand_children(true);
369 allowed_cookies_tree_
->SetController(this);
371 block_allowed_button_
= new views::LabelButton(this,
372 l10n_util::GetStringUTF16(IDS_COLLECTED_COOKIES_BLOCK_BUTTON
));
373 block_allowed_button_
->SetStyle(views::Button::STYLE_BUTTON
);
375 delete_allowed_button_
= new views::LabelButton(this,
376 l10n_util::GetStringUTF16(IDS_COOKIES_REMOVE_LABEL
));
377 delete_allowed_button_
->SetStyle(views::Button::STYLE_BUTTON
);
379 // Create the view that holds all the controls together. This will be the
380 // pane added to the tabbed pane.
381 using views::GridLayout
;
383 views::View
* pane
= new views::View();
384 GridLayout
* layout
= GridLayout::CreatePanel(pane
);
385 layout
->SetInsets(kVPanelPadding
, views::kButtonHEdgeMarginNew
,
386 kVPanelPadding
, views::kButtonHEdgeMarginNew
);
387 pane
->SetLayoutManager(layout
);
389 const int single_column_layout_id
= 0;
390 views::ColumnSet
* column_set
= layout
->AddColumnSet(single_column_layout_id
);
391 column_set
->AddColumn(GridLayout::LEADING
, GridLayout::FILL
, 1,
392 GridLayout::USE_PREF
, 0, 0);
394 const int three_columns_layout_id
= 1;
395 column_set
= layout
->AddColumnSet(three_columns_layout_id
);
396 column_set
->AddColumn(GridLayout::LEADING
, GridLayout::CENTER
, 0,
397 GridLayout::USE_PREF
, 0, 0);
398 column_set
->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing
);
399 column_set
->AddColumn(GridLayout::LEADING
, GridLayout::CENTER
, 0,
400 GridLayout::USE_PREF
, 0, 0);
402 layout
->StartRow(0, single_column_layout_id
);
403 layout
->AddView(allowed_label_
);
404 layout
->AddPaddingRow(0, kLabelBottomPadding
);
406 layout
->StartRow(1, single_column_layout_id
);
407 layout
->AddView(CreateScrollView(allowed_cookies_tree_
), 1, 1,
408 GridLayout::FILL
, GridLayout::FILL
, kTreeViewWidth
,
410 layout
->AddPaddingRow(0, views::kRelatedControlVerticalSpacing
);
412 layout
->StartRow(0, three_columns_layout_id
);
413 layout
->AddView(block_allowed_button_
);
414 layout
->AddView(delete_allowed_button_
);
419 views::View
* CollectedCookiesViews::CreateBlockedPane() {
420 TabSpecificContentSettings
* content_settings
=
421 TabSpecificContentSettings::FromWebContents(web_contents_
);
424 Profile::FromBrowserContext(web_contents_
->GetBrowserContext());
425 PrefService
* prefs
= profile
->GetPrefs();
427 // Create the controls that go into the pane.
428 blocked_label_
= new views::Label(
429 l10n_util::GetStringUTF16(
430 prefs
->GetBoolean(prefs::kBlockThirdPartyCookies
) ?
431 IDS_COLLECTED_COOKIES_BLOCKED_THIRD_PARTY_BLOCKING_ENABLED
:
432 IDS_COLLECTED_COOKIES_BLOCKED_COOKIES_LABEL
));
433 blocked_label_
->SetMultiLine(true);
434 blocked_label_
->SetHorizontalAlignment(gfx::ALIGN_LEFT
);
435 const LocalSharedObjectsContainer
& blocked_data
=
436 content_settings
->blocked_local_shared_objects();
437 blocked_cookies_tree_model_
= blocked_data
.CreateCookiesTreeModel();
438 blocked_cookies_tree_
= new views::TreeView();
439 blocked_cookies_tree_
->SetModel(blocked_cookies_tree_model_
.get());
440 blocked_cookies_tree_
->SetRootShown(false);
441 blocked_cookies_tree_
->SetEditable(false);
442 blocked_cookies_tree_
->set_auto_expand_children(true);
443 blocked_cookies_tree_
->SetController(this);
445 allow_blocked_button_
= new views::LabelButton(this,
446 l10n_util::GetStringUTF16(IDS_COLLECTED_COOKIES_ALLOW_BUTTON
));
447 allow_blocked_button_
->SetStyle(views::Button::STYLE_BUTTON
);
448 for_session_blocked_button_
= new views::LabelButton(this,
449 l10n_util::GetStringUTF16(IDS_COLLECTED_COOKIES_SESSION_ONLY_BUTTON
));
450 for_session_blocked_button_
->SetStyle(views::Button::STYLE_BUTTON
);
452 // Create the view that holds all the controls together. This will be the
453 // pane added to the tabbed pane.
454 using views::GridLayout
;
456 views::View
* pane
= new views::View();
457 GridLayout
* layout
= GridLayout::CreatePanel(pane
);
458 layout
->SetInsets(kVPanelPadding
, views::kButtonHEdgeMarginNew
,
459 kVPanelPadding
, views::kButtonHEdgeMarginNew
);
460 pane
->SetLayoutManager(layout
);
462 const int single_column_layout_id
= 0;
463 views::ColumnSet
* column_set
= layout
->AddColumnSet(single_column_layout_id
);
464 column_set
->AddColumn(GridLayout::LEADING
, GridLayout::FILL
, 1,
465 GridLayout::USE_PREF
, 0, 0);
467 const int three_columns_layout_id
= 1;
468 column_set
= layout
->AddColumnSet(three_columns_layout_id
);
469 column_set
->AddColumn(GridLayout::LEADING
, GridLayout::CENTER
, 0,
470 GridLayout::USE_PREF
, 0, 0);
471 column_set
->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing
);
472 column_set
->AddColumn(GridLayout::LEADING
, GridLayout::CENTER
, 0,
473 GridLayout::USE_PREF
, 0, 0);
475 layout
->StartRow(0, single_column_layout_id
);
476 layout
->AddView(blocked_label_
, 1, 1, GridLayout::FILL
, GridLayout::FILL
);
477 layout
->AddPaddingRow(0, kLabelBottomPadding
);
479 layout
->StartRow(1, single_column_layout_id
);
481 CreateScrollView(blocked_cookies_tree_
), 1, 1,
482 GridLayout::FILL
, GridLayout::FILL
, kTreeViewWidth
, kTreeViewHeight
);
483 layout
->AddPaddingRow(0, views::kRelatedControlVerticalSpacing
);
485 layout
->StartRow(0, three_columns_layout_id
);
486 layout
->AddView(allow_blocked_button_
);
487 layout
->AddView(for_session_blocked_button_
);
492 views::View
* CollectedCookiesViews::CreateScrollView(views::TreeView
* pane
) {
493 views::ScrollView
* scroll_view
= new views::ScrollView();
494 scroll_view
->SetContents(pane
);
495 scroll_view
->SetBorder(
496 views::Border::CreateSolidBorder(1, kCookiesBorderColor
));
500 void CollectedCookiesViews::EnableControls() {
501 bool enable_allowed_buttons
= false;
502 ui::TreeModelNode
* node
= allowed_cookies_tree_
->GetSelectedNode();
504 CookieTreeNode
* cookie_node
= static_cast<CookieTreeNode
*>(node
);
505 if (cookie_node
->GetDetailedInfo().node_type
==
506 CookieTreeNode::DetailedInfo::TYPE_HOST
) {
507 enable_allowed_buttons
= static_cast<CookieTreeHostNode
*>(
508 cookie_node
)->CanCreateContentException();
511 block_allowed_button_
->SetEnabled(enable_allowed_buttons
);
512 delete_allowed_button_
->SetEnabled(node
!= NULL
);
514 bool enable_blocked_buttons
= false;
515 node
= blocked_cookies_tree_
->GetSelectedNode();
517 CookieTreeNode
* cookie_node
= static_cast<CookieTreeNode
*>(node
);
518 if (cookie_node
->GetDetailedInfo().node_type
==
519 CookieTreeNode::DetailedInfo::TYPE_HOST
) {
520 enable_blocked_buttons
= static_cast<CookieTreeHostNode
*>(
521 cookie_node
)->CanCreateContentException();
524 allow_blocked_button_
->SetEnabled(enable_blocked_buttons
);
525 for_session_blocked_button_
->SetEnabled(enable_blocked_buttons
);
528 void CollectedCookiesViews::ShowCookieInfo() {
529 ui::TreeModelNode
* node
= allowed_cookies_tree_
->GetSelectedNode();
531 node
= blocked_cookies_tree_
->GetSelectedNode();
534 CookieTreeNode
* cookie_node
= static_cast<CookieTreeNode
*>(node
);
535 const CookieTreeNode::DetailedInfo detailed_info
=
536 cookie_node
->GetDetailedInfo();
538 if (detailed_info
.node_type
== CookieTreeNode::DetailedInfo::TYPE_COOKIE
) {
539 cookie_info_view_
->SetCookie(detailed_info
.cookie
->Domain(),
540 *detailed_info
.cookie
);
542 cookie_info_view_
->ClearCookieDisplay();
545 cookie_info_view_
->ClearCookieDisplay();
549 void CollectedCookiesViews::AddContentException(views::TreeView
* tree_view
,
550 ContentSetting setting
) {
551 CookieTreeHostNode
* host_node
=
552 static_cast<CookieTreeHostNode
*>(tree_view
->GetSelectedNode());
554 Profile::FromBrowserContext(web_contents_
->GetBrowserContext());
555 host_node
->CreateContentException(
556 CookieSettings::Factory::GetForProfile(profile
).get(), setting
);
557 infobar_
->UpdateVisibility(true, setting
, host_node
->GetTitle());
558 status_changed_
= true;
561 ///////////////////////////////////////////////////////////////////////////////
562 // CollectedCookiesViews, content::NotificationObserver implementation:
564 void CollectedCookiesViews::Observe(
566 const content::NotificationSource
& source
,
567 const content::NotificationDetails
& details
) {
568 DCHECK_EQ(chrome::NOTIFICATION_COLLECTED_COOKIES_SHOWN
, type
);