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/api/infobars/infobar_service.h"
9 #include "chrome/browser/browsing_data/browsing_data_appcache_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/browsing_data_server_bound_cert_helper.h"
16 #include "chrome/browser/browsing_data/cookies_tree_model.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/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/browser/ui/web_contents_modal_dialog_manager.h"
25 #include "chrome/common/chrome_notification_types.h"
26 #include "chrome/common/pref_names.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 "content/public/browser/web_contents_view.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/controls/button/label_button.h"
39 #include "ui/views/controls/image_view.h"
40 #include "ui/views/controls/label.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"
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
);
60 // Spacing between the infobar frame and its contents.
61 const int kInfobarVerticalPadding
= 3;
62 const int kInfobarHorizontalPadding
= 8;
64 // Width of the infobar frame.
65 const int kInfobarBorderSize
= 1;
67 // Dimensions of the tree views.
68 const int kTreeViewWidth
= 400;
69 const int kTreeViewHeight
= 125;
73 // A custom view that conditionally displays an infobar.
74 class InfobarView
: public views::View
{
77 content_
= new views::View
;
78 #if defined(USE_AURA) || !defined(OS_WIN)
79 SkColor border_color
= SK_ColorGRAY
;
81 SkColor border_color
= color_utils::GetSysSkColor(COLOR_3DSHADOW
);
83 views::Border
* border
= views::Border::CreateSolidBorder(
84 kInfobarBorderSize
, border_color
);
85 content_
->set_border(border
);
87 ui::ResourceBundle
& rb
= ui::ResourceBundle::GetSharedInstance();
88 info_image_
= new views::ImageView();
89 info_image_
->SetImage(rb
.GetImageSkiaNamed(IDR_INFO
));
90 label_
= new views::Label();
92 virtual ~InfobarView() {}
94 // Update the visibility of the infobar. If |is_visible| is true, a rule for
95 // |setting| on |domain_name| was created.
96 void UpdateVisibility(bool is_visible
,
97 ContentSetting setting
,
98 const string16
& domain_name
) {
106 case CONTENT_SETTING_BLOCK
:
107 label
= l10n_util::GetStringFUTF16(
108 IDS_COLLECTED_COOKIES_BLOCK_RULE_CREATED
, domain_name
);
111 case CONTENT_SETTING_ALLOW
:
112 label
= l10n_util::GetStringFUTF16(
113 IDS_COLLECTED_COOKIES_ALLOW_RULE_CREATED
, domain_name
);
116 case CONTENT_SETTING_SESSION_ONLY
:
117 label
= l10n_util::GetStringFUTF16(
118 IDS_COLLECTED_COOKIES_SESSION_RULE_CREATED
, domain_name
);
124 label_
->SetText(label
);
130 // Initialize contents and layout.
132 AddChildView(content_
);
133 content_
->SetLayoutManager(
134 new views::BoxLayout(views::BoxLayout::kHorizontal
,
135 kInfobarHorizontalPadding
,
136 kInfobarVerticalPadding
,
137 views::kRelatedControlSmallHorizontalSpacing
));
138 content_
->AddChildView(info_image_
);
139 content_
->AddChildView(label_
);
140 UpdateVisibility(false, CONTENT_SETTING_BLOCK
, string16());
143 // views::View overrides.
144 virtual gfx::Size
GetPreferredSize() OVERRIDE
{
148 // Add space around the banner.
149 gfx::Size
size(content_
->GetPreferredSize());
150 size
.Enlarge(0, 2 * views::kRelatedControlVerticalSpacing
);
154 virtual void Layout() OVERRIDE
{
156 0, views::kRelatedControlVerticalSpacing
,
157 width(), height() - views::kRelatedControlVerticalSpacing
);
160 virtual void ViewHierarchyChanged(bool is_add
,
162 views::View
* child
) OVERRIDE
{
163 if (is_add
&& child
== this)
167 // Holds the info icon image and text label and renders the border.
168 views::View
* content_
;
170 views::ImageView
* info_image_
;
171 // The label responsible for rendering the text.
172 views::Label
* label_
;
174 DISALLOW_COPY_AND_ASSIGN(InfobarView
);
177 ///////////////////////////////////////////////////////////////////////////////
178 // CollectedCookiesViews, public:
180 CollectedCookiesViews::CollectedCookiesViews(content::WebContents
* web_contents
)
181 : web_contents_(web_contents
),
182 allowed_label_(NULL
),
183 blocked_label_(NULL
),
184 allowed_cookies_tree_(NULL
),
185 blocked_cookies_tree_(NULL
),
186 block_allowed_button_(NULL
),
187 allow_blocked_button_(NULL
),
188 for_session_blocked_button_(NULL
),
189 cookie_info_view_(NULL
),
191 status_changed_(false) {
192 TabSpecificContentSettings
* content_settings
=
193 TabSpecificContentSettings::FromWebContents(web_contents
);
194 registrar_
.Add(this, chrome::NOTIFICATION_COLLECTED_COOKIES_SHOWN
,
195 content::Source
<TabSpecificContentSettings
>(content_settings
));
196 window_
= CreateWebContentsModalDialogViews(
198 web_contents
->GetView()->GetNativeView());
199 WebContentsModalDialogManager
* web_contents_modal_dialog_manager
=
200 WebContentsModalDialogManager::FromWebContents(web_contents
);
201 web_contents_modal_dialog_manager
->ShowDialog(window_
->GetNativeView());
204 ///////////////////////////////////////////////////////////////////////////////
205 // CollectedCookiesViews, views::DialogDelegate implementation:
207 string16
CollectedCookiesViews::GetWindowTitle() const {
208 return l10n_util::GetStringUTF16(IDS_COLLECTED_COOKIES_DIALOG_TITLE
);
211 int CollectedCookiesViews::GetDialogButtons() const {
212 return ui::DIALOG_BUTTON_CANCEL
;
215 string16
CollectedCookiesViews::GetDialogButtonLabel(
216 ui::DialogButton button
) const {
217 return l10n_util::GetStringUTF16(IDS_CLOSE
);
220 void CollectedCookiesViews::DeleteDelegate() {
224 bool CollectedCookiesViews::Cancel() {
225 if (status_changed_
) {
226 CollectedCookiesInfoBarDelegate::Create(
227 InfoBarService::FromWebContents(web_contents_
));
233 // TODO(wittman): Remove this override once we move to the new style frame view
235 views::NonClientFrameView
* CollectedCookiesViews::CreateNonClientFrameView(
236 views::Widget
* widget
) {
237 return CreateConstrainedStyleNonClientFrameView(
239 web_contents_
->GetBrowserContext());
242 ui::ModalType
CollectedCookiesViews::GetModalType() const {
244 return ui::MODAL_TYPE_CHILD
;
246 return views::WidgetDelegate::GetModalType();
250 ///////////////////////////////////////////////////////////////////////////////
251 // CollectedCookiesViews, views::ButtonListener implementation:
253 void CollectedCookiesViews::ButtonPressed(views::Button
* sender
,
254 const ui::Event
& event
) {
255 if (sender
== block_allowed_button_
)
256 AddContentException(allowed_cookies_tree_
, CONTENT_SETTING_BLOCK
);
257 else if (sender
== allow_blocked_button_
)
258 AddContentException(blocked_cookies_tree_
, CONTENT_SETTING_ALLOW
);
259 else if (sender
== for_session_blocked_button_
)
260 AddContentException(blocked_cookies_tree_
, CONTENT_SETTING_SESSION_ONLY
);
263 ///////////////////////////////////////////////////////////////////////////////
264 // CollectedCookiesViews, views::TabbedPaneListener implementation:
266 void CollectedCookiesViews::TabSelectedAt(int index
) {
271 ///////////////////////////////////////////////////////////////////////////////
272 // CollectedCookiesViews, views::TreeViewController implementation:
274 void CollectedCookiesViews::OnTreeViewSelectionChanged(
275 views::TreeView
* tree_view
) {
280 ///////////////////////////////////////////////////////////////////////////////
281 // CollectedCookiesViews, views::View overrides:
283 void CollectedCookiesViews::ViewHierarchyChanged(bool is_add
,
285 views::View
* child
) {
286 if (is_add
&& child
== this)
290 ////////////////////////////////////////////////////////////////////////////////
291 // CollectedCookiesViews, private:
293 CollectedCookiesViews::~CollectedCookiesViews() {
294 allowed_cookies_tree_
->SetModel(NULL
);
295 blocked_cookies_tree_
->SetModel(NULL
);
298 void CollectedCookiesViews::Init() {
299 using views::GridLayout
;
301 GridLayout
* layout
= GridLayout::CreatePanel(this);
302 SetLayoutManager(layout
);
304 const int single_column_layout_id
= 0;
305 views::ColumnSet
* column_set
= layout
->AddColumnSet(single_column_layout_id
);
306 column_set
->AddColumn(GridLayout::FILL
, GridLayout::FILL
, 1,
307 GridLayout::USE_PREF
, 0, 0);
309 layout
->StartRow(0, single_column_layout_id
);
310 views::TabbedPane
* tabbed_pane
= new views::TabbedPane();
311 // This color matches tabbed_pane.cc's kTabBorderColor.
312 const SkColor border_color
= SkColorSetRGB(0xCC, 0xCC, 0xCC);
313 // TODO(msw): Remove border and expand bounds in new dialog style.
314 tabbed_pane
->set_border(views::Border::CreateSolidBorder(1, border_color
));
316 layout
->AddView(tabbed_pane
);
317 // NOTE: Panes must be added after |tabbed_pane| has been added to its parent.
318 string16 label_allowed
= l10n_util::GetStringUTF16(
319 IDS_COLLECTED_COOKIES_ALLOWED_COOKIES_TAB_LABEL
);
320 string16 label_blocked
= l10n_util::GetStringUTF16(
321 IDS_COLLECTED_COOKIES_BLOCKED_COOKIES_TAB_LABEL
);
322 tabbed_pane
->AddTab(label_allowed
, CreateAllowedPane());
323 tabbed_pane
->AddTab(label_blocked
, CreateBlockedPane());
324 tabbed_pane
->SelectTabAt(0);
325 tabbed_pane
->set_listener(this);
326 layout
->AddPaddingRow(0, views::kRelatedControlVerticalSpacing
);
328 layout
->StartRow(0, single_column_layout_id
);
329 cookie_info_view_
= new CookieInfoView(false);
330 layout
->AddView(cookie_info_view_
);
331 layout
->AddPaddingRow(0, views::kRelatedControlVerticalSpacing
);
333 layout
->StartRow(0, single_column_layout_id
);
334 infobar_
= new InfobarView();
335 layout
->AddView(infobar_
);
341 views::View
* CollectedCookiesViews::CreateAllowedPane() {
342 TabSpecificContentSettings
* content_settings
=
343 TabSpecificContentSettings::FromWebContents(web_contents_
);
345 // Create the controls that go into the pane.
346 allowed_label_
= new views::Label(l10n_util::GetStringUTF16(
347 IDS_COLLECTED_COOKIES_ALLOWED_COOKIES_LABEL
));
349 const LocalSharedObjectsContainer
& allowed_data
=
350 content_settings
->allowed_local_shared_objects();
351 allowed_cookies_tree_model_
= allowed_data
.CreateCookiesTreeModel();
352 allowed_cookies_tree_
= new views::TreeView();
353 allowed_cookies_tree_
->SetModel(allowed_cookies_tree_model_
.get());
354 allowed_cookies_tree_
->SetRootShown(false);
355 allowed_cookies_tree_
->SetEditable(false);
356 allowed_cookies_tree_
->set_auto_expand_children(true);
357 allowed_cookies_tree_
->SetController(this);
359 block_allowed_button_
= new views::LabelButton(this,
360 l10n_util::GetStringUTF16(IDS_COLLECTED_COOKIES_BLOCK_BUTTON
));
361 block_allowed_button_
->SetStyle(views::Button::STYLE_NATIVE_TEXTBUTTON
);
363 // Create the view that holds all the controls together. This will be the
364 // pane added to the tabbed pane.
365 using views::GridLayout
;
367 views::View
* pane
= new views::View();
368 GridLayout
* layout
= GridLayout::CreatePanel(pane
);
369 pane
->SetLayoutManager(layout
);
371 const int single_column_layout_id
= 0;
372 views::ColumnSet
* column_set
= layout
->AddColumnSet(single_column_layout_id
);
373 column_set
->AddColumn(GridLayout::LEADING
, GridLayout::FILL
, 1,
374 GridLayout::USE_PREF
, 0, 0);
376 layout
->StartRow(0, single_column_layout_id
);
377 layout
->AddView(allowed_label_
);
378 layout
->AddPaddingRow(0, views::kRelatedControlVerticalSpacing
);
380 layout
->StartRow(1, single_column_layout_id
);
381 layout
->AddView(allowed_cookies_tree_
->CreateParentIfNecessary(), 1, 1,
382 GridLayout::FILL
, GridLayout::FILL
, kTreeViewWidth
,
384 layout
->AddPaddingRow(0, views::kRelatedControlVerticalSpacing
);
386 layout
->StartRow(0, single_column_layout_id
);
387 layout
->AddView(block_allowed_button_
, 1, 1, GridLayout::LEADING
,
393 views::View
* CollectedCookiesViews::CreateBlockedPane() {
394 TabSpecificContentSettings
* content_settings
=
395 TabSpecificContentSettings::FromWebContents(web_contents_
);
398 Profile::FromBrowserContext(web_contents_
->GetBrowserContext());
399 PrefService
* prefs
= profile
->GetPrefs();
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);
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_NATIVE_TEXTBUTTON
);
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_NATIVE_TEXTBUTTON
);
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
;
430 views::View
* pane
= new views::View();
431 GridLayout
* layout
= GridLayout::CreatePanel(pane
);
432 pane
->SetLayoutManager(layout
);
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);
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);
447 layout
->StartRow(0, single_column_layout_id
);
448 layout
->AddView(blocked_label_
, 1, 1, GridLayout::FILL
, GridLayout::FILL
);
449 layout
->AddPaddingRow(0, views::kRelatedControlVerticalSpacing
);
451 layout
->StartRow(1, single_column_layout_id
);
453 blocked_cookies_tree_
->CreateParentIfNecessary(), 1, 1,
454 GridLayout::FILL
, GridLayout::FILL
, kTreeViewWidth
, kTreeViewHeight
);
455 layout
->AddPaddingRow(0, views::kRelatedControlVerticalSpacing
);
457 layout
->StartRow(0, three_columns_layout_id
);
458 layout
->AddView(allow_blocked_button_
);
459 layout
->AddView(for_session_blocked_button_
);
464 void CollectedCookiesViews::EnableControls() {
465 bool enable_allowed_buttons
= false;
466 ui::TreeModelNode
* node
= allowed_cookies_tree_
->GetSelectedNode();
468 CookieTreeNode
* cookie_node
= static_cast<CookieTreeNode
*>(node
);
469 if (cookie_node
->GetDetailedInfo().node_type
==
470 CookieTreeNode::DetailedInfo::TYPE_HOST
) {
471 enable_allowed_buttons
= static_cast<CookieTreeHostNode
*>(
472 cookie_node
)->CanCreateContentException();
475 block_allowed_button_
->SetEnabled(enable_allowed_buttons
);
477 bool enable_blocked_buttons
= false;
478 node
= blocked_cookies_tree_
->GetSelectedNode();
480 CookieTreeNode
* cookie_node
= static_cast<CookieTreeNode
*>(node
);
481 if (cookie_node
->GetDetailedInfo().node_type
==
482 CookieTreeNode::DetailedInfo::TYPE_HOST
) {
483 enable_blocked_buttons
= static_cast<CookieTreeHostNode
*>(
484 cookie_node
)->CanCreateContentException();
487 allow_blocked_button_
->SetEnabled(enable_blocked_buttons
);
488 for_session_blocked_button_
->SetEnabled(enable_blocked_buttons
);
491 void CollectedCookiesViews::ShowCookieInfo() {
492 ui::TreeModelNode
* node
= allowed_cookies_tree_
->GetSelectedNode();
494 node
= blocked_cookies_tree_
->GetSelectedNode();
497 CookieTreeNode
* cookie_node
= static_cast<CookieTreeNode
*>(node
);
498 const CookieTreeNode::DetailedInfo detailed_info
=
499 cookie_node
->GetDetailedInfo();
501 if (detailed_info
.node_type
== CookieTreeNode::DetailedInfo::TYPE_COOKIE
) {
502 cookie_info_view_
->SetCookie(detailed_info
.cookie
->Domain(),
503 *detailed_info
.cookie
);
505 cookie_info_view_
->ClearCookieDisplay();
508 cookie_info_view_
->ClearCookieDisplay();
512 void CollectedCookiesViews::AddContentException(views::TreeView
* tree_view
,
513 ContentSetting setting
) {
514 CookieTreeHostNode
* host_node
=
515 static_cast<CookieTreeHostNode
*>(tree_view
->GetSelectedNode());
517 Profile::FromBrowserContext(web_contents_
->GetBrowserContext());
518 host_node
->CreateContentException(
519 CookieSettings::Factory::GetForProfile(profile
), setting
);
520 infobar_
->UpdateVisibility(true, setting
, host_node
->GetTitle());
521 status_changed_
= true;
524 ///////////////////////////////////////////////////////////////////////////////
525 // CollectedCookiesViews, content::NotificationObserver implementation:
527 void CollectedCookiesViews::Observe(
529 const content::NotificationSource
& source
,
530 const content::NotificationDetails
& details
) {
531 DCHECK_EQ(chrome::NOTIFICATION_COLLECTED_COOKIES_SHOWN
, type
);