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_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/constrained_window_views.h"
23 #include "chrome/browser/ui/views/cookie_info_view.h"
24 #include "chrome/common/pref_names.h"
25 #include "chrome/grit/generated_resources.h"
26 #include "chrome/grit/locale_settings.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"
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
);
59 // Spacing between the infobar frame and its contents.
60 const int kInfobarVerticalPadding
= 3;
61 const int kInfobarHorizontalPadding
= 8;
63 // Width of the infobar frame.
64 const int kInfobarBorderSize
= 1;
66 // Dimensions of the tree views.
67 const int kTreeViewWidth
= 400;
68 const int kTreeViewHeight
= 125;
70 // The color of the border around the cookies tree view.
71 const SkColor kCookiesBorderColor
= SkColorSetRGB(0xC8, 0xC8, 0xC8);
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;
81 // A custom view that conditionally displays an infobar.
82 class InfobarView
: public views::View
{
85 content_
= new views::View
;
86 SkColor border_color
= SK_ColorGRAY
;
88 views::Border::CreateSolidBorder(kInfobarBorderSize
, border_color
));
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();
95 virtual ~InfobarView() {}
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
) {
107 base::string16 label
;
109 case CONTENT_SETTING_BLOCK
:
110 label
= l10n_util::GetStringFUTF16(
111 IDS_COLLECTED_COOKIES_BLOCK_RULE_CREATED
, domain_name
);
114 case CONTENT_SETTING_ALLOW
:
115 label
= l10n_util::GetStringFUTF16(
116 IDS_COLLECTED_COOKIES_ALLOW_RULE_CREATED
, domain_name
);
119 case CONTENT_SETTING_SESSION_ONLY
:
120 label
= l10n_util::GetStringFUTF16(
121 IDS_COLLECTED_COOKIES_SESSION_RULE_CREATED
, domain_name
);
127 label_
->SetText(label
);
133 // Initialize contents and layout.
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());
146 // views::View overrides.
147 virtual gfx::Size
GetPreferredSize() const override
{
151 // Add space around the banner.
152 gfx::Size
size(content_
->GetPreferredSize());
153 size
.Enlarge(0, 2 * views::kRelatedControlVerticalSpacing
);
157 virtual void Layout() override
{
159 0, views::kRelatedControlVerticalSpacing
,
160 width(), height() - views::kRelatedControlVerticalSpacing
);
163 virtual void ViewHierarchyChanged(
164 const ViewHierarchyChangedDetails
& details
) override
{
165 if (details
.is_add
&& details
.child
== this)
169 // Holds the info icon image and text label and renders the border.
170 views::View
* content_
;
172 views::ImageView
* info_image_
;
173 // The label responsible for rendering the text.
174 views::Label
* label_
;
176 DISALLOW_COPY_AND_ASSIGN(InfobarView
);
179 ///////////////////////////////////////////////////////////////////////////////
180 // CollectedCookiesViews, public:
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
),
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
);
202 ///////////////////////////////////////////////////////////////////////////////
203 // CollectedCookiesViews, views::DialogDelegate implementation:
205 base::string16
CollectedCookiesViews::GetWindowTitle() const {
206 return l10n_util::GetStringUTF16(IDS_COLLECTED_COOKIES_DIALOG_TITLE
);
209 int CollectedCookiesViews::GetDialogButtons() const {
210 return ui::DIALOG_BUTTON_CANCEL
;
213 base::string16
CollectedCookiesViews::GetDialogButtonLabel(
214 ui::DialogButton button
) const {
215 return l10n_util::GetStringUTF16(IDS_CLOSE
);
218 bool CollectedCookiesViews::Cancel() {
219 if (status_changed_
) {
220 CollectedCookiesInfoBarDelegate::Create(
221 InfoBarService::FromWebContents(web_contents_
));
226 ui::ModalType
CollectedCookiesViews::GetModalType() const {
227 return ui::MODAL_TYPE_CHILD
;
230 ///////////////////////////////////////////////////////////////////////////////
231 // CollectedCookiesViews, views::ButtonListener implementation:
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
);
247 ///////////////////////////////////////////////////////////////////////////////
248 // CollectedCookiesViews, views::TabbedPaneListener implementation:
250 void CollectedCookiesViews::TabSelectedAt(int index
) {
255 ///////////////////////////////////////////////////////////////////////////////
256 // CollectedCookiesViews, views::TreeViewController implementation:
258 void CollectedCookiesViews::OnTreeViewSelectionChanged(
259 views::TreeView
* tree_view
) {
264 ///////////////////////////////////////////////////////////////////////////////
265 // CollectedCookiesViews, views::View overrides:
267 gfx::Size
CollectedCookiesViews::GetMinimumSize() const {
268 // Allow UpdateWebContentsModalDialogPosition to clamp the dialog width.
269 return gfx::Size(0, View::GetMinimumSize().height());
272 void CollectedCookiesViews::ViewHierarchyChanged(
273 const ViewHierarchyChangedDetails
& details
) {
274 if (details
.is_add
&& details
.child
== this)
278 ////////////////////////////////////////////////////////////////////////////////
279 // CollectedCookiesViews, private:
281 CollectedCookiesViews::~CollectedCookiesViews() {
282 allowed_cookies_tree_
->SetModel(NULL
);
283 blocked_cookies_tree_
->SetModel(NULL
);
286 void CollectedCookiesViews::Init() {
287 using views::GridLayout
;
289 GridLayout
* layout
= GridLayout::CreatePanel(this);
290 SetLayoutManager(layout
);
292 const int single_column_layout_id
= 0;
293 views::ColumnSet
* column_set
= layout
->AddColumnSet(single_column_layout_id
);
294 column_set
->AddColumn(GridLayout::FILL
, GridLayout::FILL
, 1,
295 GridLayout::USE_PREF
, 0, 0);
297 layout
->StartRow(0, single_column_layout_id
);
298 views::TabbedPane
* tabbed_pane
= new views::TabbedPane();
299 layout
->SetInsets(gfx::Insets(kTabbedPaneTopPadding
, 0, 0, 0));
301 layout
->AddView(tabbed_pane
);
302 // NOTE: Panes must be added after |tabbed_pane| has been added to its parent.
303 base::string16 label_allowed
= l10n_util::GetStringUTF16(
304 IDS_COLLECTED_COOKIES_ALLOWED_COOKIES_TAB_LABEL
);
305 base::string16 label_blocked
= l10n_util::GetStringUTF16(
306 IDS_COLLECTED_COOKIES_BLOCKED_COOKIES_TAB_LABEL
);
307 tabbed_pane
->AddTab(label_allowed
, CreateAllowedPane());
308 tabbed_pane
->AddTab(label_blocked
, CreateBlockedPane());
309 tabbed_pane
->SelectTabAt(0);
310 tabbed_pane
->set_listener(this);
311 layout
->AddPaddingRow(0, views::kRelatedControlVerticalSpacing
);
313 layout
->StartRow(0, single_column_layout_id
);
314 cookie_info_view_
= new CookieInfoView();
315 layout
->AddView(cookie_info_view_
);
316 layout
->AddPaddingRow(0, kCookieInfoBottomPadding
);
318 layout
->StartRow(0, single_column_layout_id
);
319 infobar_
= new InfobarView();
320 layout
->AddView(infobar_
);
326 views::View
* CollectedCookiesViews::CreateAllowedPane() {
327 TabSpecificContentSettings
* content_settings
=
328 TabSpecificContentSettings::FromWebContents(web_contents_
);
330 // Create the controls that go into the pane.
331 allowed_label_
= new views::Label(l10n_util::GetStringUTF16(
332 IDS_COLLECTED_COOKIES_ALLOWED_COOKIES_LABEL
));
334 allowed_cookies_tree_model_
=
335 content_settings
->CreateAllowedCookiesTreeModel();
336 allowed_cookies_tree_
= new views::TreeView();
337 allowed_cookies_tree_
->SetModel(allowed_cookies_tree_model_
.get());
338 allowed_cookies_tree_
->SetRootShown(false);
339 allowed_cookies_tree_
->SetEditable(false);
340 allowed_cookies_tree_
->set_auto_expand_children(true);
341 allowed_cookies_tree_
->SetController(this);
343 block_allowed_button_
= new views::LabelButton(this,
344 l10n_util::GetStringUTF16(IDS_COLLECTED_COOKIES_BLOCK_BUTTON
));
345 block_allowed_button_
->SetStyle(views::Button::STYLE_BUTTON
);
347 delete_allowed_button_
= new views::LabelButton(this,
348 l10n_util::GetStringUTF16(IDS_COOKIES_REMOVE_LABEL
));
349 delete_allowed_button_
->SetStyle(views::Button::STYLE_BUTTON
);
351 // Create the view that holds all the controls together. This will be the
352 // pane added to the tabbed pane.
353 using views::GridLayout
;
355 views::View
* pane
= new views::View();
356 GridLayout
* layout
= GridLayout::CreatePanel(pane
);
357 layout
->SetInsets(kVPanelPadding
, views::kButtonHEdgeMarginNew
,
358 kVPanelPadding
, views::kButtonHEdgeMarginNew
);
359 pane
->SetLayoutManager(layout
);
361 const int single_column_layout_id
= 0;
362 views::ColumnSet
* column_set
= layout
->AddColumnSet(single_column_layout_id
);
363 column_set
->AddColumn(GridLayout::LEADING
, GridLayout::FILL
, 1,
364 GridLayout::USE_PREF
, 0, 0);
366 const int three_columns_layout_id
= 1;
367 column_set
= layout
->AddColumnSet(three_columns_layout_id
);
368 column_set
->AddColumn(GridLayout::LEADING
, GridLayout::CENTER
, 0,
369 GridLayout::USE_PREF
, 0, 0);
370 column_set
->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing
);
371 column_set
->AddColumn(GridLayout::LEADING
, GridLayout::CENTER
, 0,
372 GridLayout::USE_PREF
, 0, 0);
374 layout
->StartRow(0, single_column_layout_id
);
375 layout
->AddView(allowed_label_
);
376 layout
->AddPaddingRow(0, kLabelBottomPadding
);
378 layout
->StartRow(1, single_column_layout_id
);
379 layout
->AddView(CreateScrollView(allowed_cookies_tree_
), 1, 1,
380 GridLayout::FILL
, GridLayout::FILL
, kTreeViewWidth
,
382 layout
->AddPaddingRow(0, views::kRelatedControlVerticalSpacing
);
384 layout
->StartRow(0, three_columns_layout_id
);
385 layout
->AddView(block_allowed_button_
);
386 layout
->AddView(delete_allowed_button_
);
391 views::View
* CollectedCookiesViews::CreateBlockedPane() {
392 TabSpecificContentSettings
* content_settings
=
393 TabSpecificContentSettings::FromWebContents(web_contents_
);
396 Profile::FromBrowserContext(web_contents_
->GetBrowserContext());
397 PrefService
* prefs
= profile
->GetPrefs();
399 // Create the controls that go into the pane.
400 blocked_label_
= new views::Label(
401 l10n_util::GetStringUTF16(
402 prefs
->GetBoolean(prefs::kBlockThirdPartyCookies
) ?
403 IDS_COLLECTED_COOKIES_BLOCKED_THIRD_PARTY_BLOCKING_ENABLED
:
404 IDS_COLLECTED_COOKIES_BLOCKED_COOKIES_LABEL
));
405 blocked_label_
->SetMultiLine(true);
406 blocked_label_
->SetHorizontalAlignment(gfx::ALIGN_LEFT
);
407 blocked_cookies_tree_model_
=
408 content_settings
->CreateBlockedCookiesTreeModel();
409 blocked_cookies_tree_
= new views::TreeView();
410 blocked_cookies_tree_
->SetModel(blocked_cookies_tree_model_
.get());
411 blocked_cookies_tree_
->SetRootShown(false);
412 blocked_cookies_tree_
->SetEditable(false);
413 blocked_cookies_tree_
->set_auto_expand_children(true);
414 blocked_cookies_tree_
->SetController(this);
416 allow_blocked_button_
= new views::LabelButton(this,
417 l10n_util::GetStringUTF16(IDS_COLLECTED_COOKIES_ALLOW_BUTTON
));
418 allow_blocked_button_
->SetStyle(views::Button::STYLE_BUTTON
);
419 for_session_blocked_button_
= new views::LabelButton(this,
420 l10n_util::GetStringUTF16(IDS_COLLECTED_COOKIES_SESSION_ONLY_BUTTON
));
421 for_session_blocked_button_
->SetStyle(views::Button::STYLE_BUTTON
);
423 // Create the view that holds all the controls together. This will be the
424 // pane added to the tabbed pane.
425 using views::GridLayout
;
427 views::View
* pane
= new views::View();
428 GridLayout
* layout
= GridLayout::CreatePanel(pane
);
429 layout
->SetInsets(kVPanelPadding
, views::kButtonHEdgeMarginNew
,
430 kVPanelPadding
, views::kButtonHEdgeMarginNew
);
431 pane
->SetLayoutManager(layout
);
433 const int single_column_layout_id
= 0;
434 views::ColumnSet
* column_set
= layout
->AddColumnSet(single_column_layout_id
);
435 column_set
->AddColumn(GridLayout::LEADING
, GridLayout::FILL
, 1,
436 GridLayout::USE_PREF
, 0, 0);
438 const int three_columns_layout_id
= 1;
439 column_set
= layout
->AddColumnSet(three_columns_layout_id
);
440 column_set
->AddColumn(GridLayout::LEADING
, GridLayout::CENTER
, 0,
441 GridLayout::USE_PREF
, 0, 0);
442 column_set
->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing
);
443 column_set
->AddColumn(GridLayout::LEADING
, GridLayout::CENTER
, 0,
444 GridLayout::USE_PREF
, 0, 0);
446 layout
->StartRow(0, single_column_layout_id
);
447 layout
->AddView(blocked_label_
, 1, 1, GridLayout::FILL
, GridLayout::FILL
);
448 layout
->AddPaddingRow(0, kLabelBottomPadding
);
450 layout
->StartRow(1, single_column_layout_id
);
452 CreateScrollView(blocked_cookies_tree_
), 1, 1,
453 GridLayout::FILL
, GridLayout::FILL
, kTreeViewWidth
, kTreeViewHeight
);
454 layout
->AddPaddingRow(0, views::kRelatedControlVerticalSpacing
);
456 layout
->StartRow(0, three_columns_layout_id
);
457 layout
->AddView(allow_blocked_button_
);
458 layout
->AddView(for_session_blocked_button_
);
463 views::View
* CollectedCookiesViews::CreateScrollView(views::TreeView
* pane
) {
464 views::ScrollView
* scroll_view
= new views::ScrollView();
465 scroll_view
->SetContents(pane
);
466 scroll_view
->SetBorder(
467 views::Border::CreateSolidBorder(1, kCookiesBorderColor
));
471 void CollectedCookiesViews::EnableControls() {
472 bool enable_allowed_buttons
= false;
473 ui::TreeModelNode
* node
= allowed_cookies_tree_
->GetSelectedNode();
475 CookieTreeNode
* cookie_node
= static_cast<CookieTreeNode
*>(node
);
476 if (cookie_node
->GetDetailedInfo().node_type
==
477 CookieTreeNode::DetailedInfo::TYPE_HOST
) {
478 enable_allowed_buttons
= static_cast<CookieTreeHostNode
*>(
479 cookie_node
)->CanCreateContentException();
482 block_allowed_button_
->SetEnabled(enable_allowed_buttons
);
483 delete_allowed_button_
->SetEnabled(node
!= NULL
);
485 bool enable_blocked_buttons
= false;
486 node
= blocked_cookies_tree_
->GetSelectedNode();
488 CookieTreeNode
* cookie_node
= static_cast<CookieTreeNode
*>(node
);
489 if (cookie_node
->GetDetailedInfo().node_type
==
490 CookieTreeNode::DetailedInfo::TYPE_HOST
) {
491 enable_blocked_buttons
= static_cast<CookieTreeHostNode
*>(
492 cookie_node
)->CanCreateContentException();
495 allow_blocked_button_
->SetEnabled(enable_blocked_buttons
);
496 for_session_blocked_button_
->SetEnabled(enable_blocked_buttons
);
499 void CollectedCookiesViews::ShowCookieInfo() {
500 ui::TreeModelNode
* node
= allowed_cookies_tree_
->GetSelectedNode();
502 node
= blocked_cookies_tree_
->GetSelectedNode();
505 CookieTreeNode
* cookie_node
= static_cast<CookieTreeNode
*>(node
);
506 const CookieTreeNode::DetailedInfo detailed_info
=
507 cookie_node
->GetDetailedInfo();
509 if (detailed_info
.node_type
== CookieTreeNode::DetailedInfo::TYPE_COOKIE
) {
510 cookie_info_view_
->SetCookie(detailed_info
.cookie
->Domain(),
511 *detailed_info
.cookie
);
513 cookie_info_view_
->ClearCookieDisplay();
516 cookie_info_view_
->ClearCookieDisplay();
520 void CollectedCookiesViews::AddContentException(views::TreeView
* tree_view
,
521 ContentSetting setting
) {
522 CookieTreeHostNode
* host_node
=
523 static_cast<CookieTreeHostNode
*>(tree_view
->GetSelectedNode());
525 Profile::FromBrowserContext(web_contents_
->GetBrowserContext());
526 host_node
->CreateContentException(
527 CookieSettings::Factory::GetForProfile(profile
).get(), setting
);
528 infobar_
->UpdateVisibility(true, setting
, host_node
->GetTitle());
529 status_changed_
= true;
532 ///////////////////////////////////////////////////////////////////////////////
533 // CollectedCookiesViews, content::NotificationObserver implementation:
535 void CollectedCookiesViews::Observe(
537 const content::NotificationSource
& source
,
538 const content::NotificationDetails
& details
) {
539 DCHECK_EQ(chrome::NOTIFICATION_COLLECTED_COOKIES_SHOWN
, type
);
540 GetWidget()->Close();