collected_cookies_views.cc revision 90dce4d38c5ff5333bea97d859d4e484e27edf0c
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_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/content_settings/cookie_settings.h" 17#include "chrome/browser/content_settings/local_shared_objects_container.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/chrome_notification_types.h" 25#include "chrome/common/pref_names.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 "content/public/browser/web_contents_view.h" 32#include "grit/generated_resources.h" 33#include "grit/locale_settings.h" 34#include "grit/theme_resources.h" 35#include "net/cookies/canonical_cookie.h" 36#include "ui/base/l10n/l10n_util.h" 37#include "ui/base/resource/resource_bundle.h" 38#include "ui/gfx/color_utils.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/tabbed_pane/tabbed_pane.h" 43#include "ui/views/controls/tree/tree_view.h" 44#include "ui/views/layout/box_layout.h" 45#include "ui/views/layout/grid_layout.h" 46#include "ui/views/layout/layout_constants.h" 47#include "ui/views/widget/widget.h" 48 49using web_modal::WebContentsModalDialogManager; 50 51namespace chrome { 52 53// Declared in browser_dialogs.h so others don't have to depend on our header. 54void ShowCollectedCookiesDialog(content::WebContents* web_contents) { 55 // Deletes itself on close. 56 new CollectedCookiesViews(web_contents); 57} 58 59} // namespace chrome 60 61namespace { 62 63// Spacing between the infobar frame and its contents. 64const int kInfobarVerticalPadding = 3; 65const int kInfobarHorizontalPadding = 8; 66 67// Width of the infobar frame. 68const int kInfobarBorderSize = 1; 69 70// Dimensions of the tree views. 71const int kTreeViewWidth = 400; 72const int kTreeViewHeight = 125; 73 74} // namespace 75 76// A custom view that conditionally displays an infobar. 77class InfobarView : public views::View { 78 public: 79 InfobarView() { 80 content_ = new views::View; 81#if defined(USE_AURA) || !defined(OS_WIN) 82 SkColor border_color = SK_ColorGRAY; 83#else 84 SkColor border_color = color_utils::GetSysSkColor(COLOR_3DSHADOW); 85#endif 86 views::Border* border = views::Border::CreateSolidBorder( 87 kInfobarBorderSize, border_color); 88 content_->set_border(border); 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 virtual ~InfobarView() {} 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 string16& domain_name) { 102 if (!is_visible) { 103 SetVisible(false); 104 return; 105 } 106 107 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, string16()); 144 } 145 146 // views::View overrides. 147 virtual gfx::Size GetPreferredSize() 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 virtual void Layout() OVERRIDE { 158 content_->SetBounds( 159 0, views::kRelatedControlVerticalSpacing, 160 width(), height() - views::kRelatedControlVerticalSpacing); 161 } 162 163 virtual 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 182CollectedCookiesViews::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 allow_blocked_button_(NULL), 190 for_session_blocked_button_(NULL), 191 cookie_info_view_(NULL), 192 infobar_(NULL), 193 status_changed_(false) { 194 TabSpecificContentSettings* content_settings = 195 TabSpecificContentSettings::FromWebContents(web_contents); 196 registrar_.Add(this, chrome::NOTIFICATION_COLLECTED_COOKIES_SHOWN, 197 content::Source<TabSpecificContentSettings>(content_settings)); 198 WebContentsModalDialogManager* web_contents_modal_dialog_manager = 199 WebContentsModalDialogManager::FromWebContents(web_contents); 200 window_ = CreateWebContentsModalDialogViews( 201 this, 202 web_contents->GetView()->GetNativeView(), 203 web_contents_modal_dialog_manager->delegate()-> 204 GetWebContentsModalDialogHost()); 205 web_contents_modal_dialog_manager->ShowDialog(window_->GetNativeView()); 206} 207 208/////////////////////////////////////////////////////////////////////////////// 209// CollectedCookiesViews, views::DialogDelegate implementation: 210 211string16 CollectedCookiesViews::GetWindowTitle() const { 212 return l10n_util::GetStringUTF16(IDS_COLLECTED_COOKIES_DIALOG_TITLE); 213} 214 215int CollectedCookiesViews::GetDialogButtons() const { 216 return ui::DIALOG_BUTTON_CANCEL; 217} 218 219string16 CollectedCookiesViews::GetDialogButtonLabel( 220 ui::DialogButton button) const { 221 return l10n_util::GetStringUTF16(IDS_CLOSE); 222} 223 224void CollectedCookiesViews::DeleteDelegate() { 225 delete this; 226} 227 228bool CollectedCookiesViews::Cancel() { 229 if (status_changed_) { 230 CollectedCookiesInfoBarDelegate::Create( 231 InfoBarService::FromWebContents(web_contents_)); 232 } 233 234 return true; 235} 236 237// TODO(wittman): Remove this override once we move to the new style frame view 238// on all dialogs. 239views::NonClientFrameView* CollectedCookiesViews::CreateNonClientFrameView( 240 views::Widget* widget) { 241 return CreateConstrainedStyleNonClientFrameView( 242 widget, 243 web_contents_->GetBrowserContext()); 244} 245 246ui::ModalType CollectedCookiesViews::GetModalType() const { 247#if defined(USE_ASH) 248 return ui::MODAL_TYPE_CHILD; 249#else 250 return views::WidgetDelegate::GetModalType(); 251#endif 252} 253 254/////////////////////////////////////////////////////////////////////////////// 255// CollectedCookiesViews, views::ButtonListener implementation: 256 257void CollectedCookiesViews::ButtonPressed(views::Button* sender, 258 const ui::Event& event) { 259 if (sender == block_allowed_button_) 260 AddContentException(allowed_cookies_tree_, CONTENT_SETTING_BLOCK); 261 else if (sender == allow_blocked_button_) 262 AddContentException(blocked_cookies_tree_, CONTENT_SETTING_ALLOW); 263 else if (sender == for_session_blocked_button_) 264 AddContentException(blocked_cookies_tree_, CONTENT_SETTING_SESSION_ONLY); 265} 266 267/////////////////////////////////////////////////////////////////////////////// 268// CollectedCookiesViews, views::TabbedPaneListener implementation: 269 270void CollectedCookiesViews::TabSelectedAt(int index) { 271 EnableControls(); 272 ShowCookieInfo(); 273} 274 275/////////////////////////////////////////////////////////////////////////////// 276// CollectedCookiesViews, views::TreeViewController implementation: 277 278void CollectedCookiesViews::OnTreeViewSelectionChanged( 279 views::TreeView* tree_view) { 280 EnableControls(); 281 ShowCookieInfo(); 282} 283 284/////////////////////////////////////////////////////////////////////////////// 285// CollectedCookiesViews, views::View overrides: 286 287void CollectedCookiesViews::ViewHierarchyChanged( 288 const ViewHierarchyChangedDetails& details) { 289 if (details.is_add && details.child == this) 290 Init(); 291} 292 293//////////////////////////////////////////////////////////////////////////////// 294// CollectedCookiesViews, private: 295 296CollectedCookiesViews::~CollectedCookiesViews() { 297 allowed_cookies_tree_->SetModel(NULL); 298 blocked_cookies_tree_->SetModel(NULL); 299} 300 301void CollectedCookiesViews::Init() { 302 using views::GridLayout; 303 304 GridLayout* layout = GridLayout::CreatePanel(this); 305 SetLayoutManager(layout); 306 307 const int single_column_layout_id = 0; 308 views::ColumnSet* column_set = layout->AddColumnSet(single_column_layout_id); 309 column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 1, 310 GridLayout::USE_PREF, 0, 0); 311 312 layout->StartRow(0, single_column_layout_id); 313 views::TabbedPane* tabbed_pane = new views::TabbedPane(); 314 // This color matches tabbed_pane.cc's kTabBorderColor. 315 const SkColor border_color = SkColorSetRGB(0xCC, 0xCC, 0xCC); 316 // TODO(msw): Remove border and expand bounds in new dialog style. 317 tabbed_pane->set_border(views::Border::CreateSolidBorder(1, border_color)); 318 319 layout->AddView(tabbed_pane); 320 // NOTE: Panes must be added after |tabbed_pane| has been added to its parent. 321 string16 label_allowed = l10n_util::GetStringUTF16( 322 IDS_COLLECTED_COOKIES_ALLOWED_COOKIES_TAB_LABEL); 323 string16 label_blocked = l10n_util::GetStringUTF16( 324 IDS_COLLECTED_COOKIES_BLOCKED_COOKIES_TAB_LABEL); 325 tabbed_pane->AddTab(label_allowed, CreateAllowedPane()); 326 tabbed_pane->AddTab(label_blocked, CreateBlockedPane()); 327 tabbed_pane->SelectTabAt(0); 328 tabbed_pane->set_listener(this); 329 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); 330 331 layout->StartRow(0, single_column_layout_id); 332 cookie_info_view_ = new CookieInfoView(false); 333 layout->AddView(cookie_info_view_); 334 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); 335 336 layout->StartRow(0, single_column_layout_id); 337 infobar_ = new InfobarView(); 338 layout->AddView(infobar_); 339 340 EnableControls(); 341 ShowCookieInfo(); 342} 343 344views::View* CollectedCookiesViews::CreateAllowedPane() { 345 TabSpecificContentSettings* content_settings = 346 TabSpecificContentSettings::FromWebContents(web_contents_); 347 348 // Create the controls that go into the pane. 349 allowed_label_ = new views::Label(l10n_util::GetStringUTF16( 350 IDS_COLLECTED_COOKIES_ALLOWED_COOKIES_LABEL)); 351 352 const LocalSharedObjectsContainer& allowed_data = 353 content_settings->allowed_local_shared_objects(); 354 allowed_cookies_tree_model_ = allowed_data.CreateCookiesTreeModel(); 355 allowed_cookies_tree_ = new views::TreeView(); 356 allowed_cookies_tree_->SetModel(allowed_cookies_tree_model_.get()); 357 allowed_cookies_tree_->SetRootShown(false); 358 allowed_cookies_tree_->SetEditable(false); 359 allowed_cookies_tree_->set_auto_expand_children(true); 360 allowed_cookies_tree_->SetController(this); 361 362 block_allowed_button_ = new views::LabelButton(this, 363 l10n_util::GetStringUTF16(IDS_COLLECTED_COOKIES_BLOCK_BUTTON)); 364 block_allowed_button_->SetStyle(views::Button::STYLE_NATIVE_TEXTBUTTON); 365 366 // Create the view that holds all the controls together. This will be the 367 // pane added to the tabbed pane. 368 using views::GridLayout; 369 370 views::View* pane = new views::View(); 371 GridLayout* layout = GridLayout::CreatePanel(pane); 372 pane->SetLayoutManager(layout); 373 374 const int single_column_layout_id = 0; 375 views::ColumnSet* column_set = layout->AddColumnSet(single_column_layout_id); 376 column_set->AddColumn(GridLayout::LEADING, GridLayout::FILL, 1, 377 GridLayout::USE_PREF, 0, 0); 378 379 layout->StartRow(0, single_column_layout_id); 380 layout->AddView(allowed_label_); 381 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); 382 383 layout->StartRow(1, single_column_layout_id); 384 layout->AddView(allowed_cookies_tree_->CreateParentIfNecessary(), 1, 1, 385 GridLayout::FILL, GridLayout::FILL, kTreeViewWidth, 386 kTreeViewHeight); 387 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); 388 389 layout->StartRow(0, single_column_layout_id); 390 layout->AddView(block_allowed_button_, 1, 1, GridLayout::LEADING, 391 GridLayout::CENTER); 392 393 return pane; 394} 395 396views::View* CollectedCookiesViews::CreateBlockedPane() { 397 TabSpecificContentSettings* content_settings = 398 TabSpecificContentSettings::FromWebContents(web_contents_); 399 400 Profile* profile = 401 Profile::FromBrowserContext(web_contents_->GetBrowserContext()); 402 PrefService* prefs = profile->GetPrefs(); 403 404 // Create the controls that go into the pane. 405 blocked_label_ = new views::Label( 406 l10n_util::GetStringUTF16( 407 prefs->GetBoolean(prefs::kBlockThirdPartyCookies) ? 408 IDS_COLLECTED_COOKIES_BLOCKED_THIRD_PARTY_BLOCKING_ENABLED : 409 IDS_COLLECTED_COOKIES_BLOCKED_COOKIES_LABEL)); 410 blocked_label_->SetMultiLine(true); 411 blocked_label_->SetHorizontalAlignment(gfx::ALIGN_LEFT); 412 const LocalSharedObjectsContainer& blocked_data = 413 content_settings->blocked_local_shared_objects(); 414 blocked_cookies_tree_model_ = blocked_data.CreateCookiesTreeModel(); 415 blocked_cookies_tree_ = new views::TreeView(); 416 blocked_cookies_tree_->SetModel(blocked_cookies_tree_model_.get()); 417 blocked_cookies_tree_->SetRootShown(false); 418 blocked_cookies_tree_->SetEditable(false); 419 blocked_cookies_tree_->set_auto_expand_children(true); 420 blocked_cookies_tree_->SetController(this); 421 422 allow_blocked_button_ = new views::LabelButton(this, 423 l10n_util::GetStringUTF16(IDS_COLLECTED_COOKIES_ALLOW_BUTTON)); 424 allow_blocked_button_->SetStyle(views::Button::STYLE_NATIVE_TEXTBUTTON); 425 for_session_blocked_button_ = new views::LabelButton(this, 426 l10n_util::GetStringUTF16(IDS_COLLECTED_COOKIES_SESSION_ONLY_BUTTON)); 427 for_session_blocked_button_->SetStyle(views::Button::STYLE_NATIVE_TEXTBUTTON); 428 429 // Create the view that holds all the controls together. This will be the 430 // pane added to the tabbed pane. 431 using views::GridLayout; 432 433 views::View* pane = new views::View(); 434 GridLayout* layout = GridLayout::CreatePanel(pane); 435 pane->SetLayoutManager(layout); 436 437 const int single_column_layout_id = 0; 438 views::ColumnSet* column_set = layout->AddColumnSet(single_column_layout_id); 439 column_set->AddColumn(GridLayout::LEADING, GridLayout::FILL, 1, 440 GridLayout::USE_PREF, 0, 0); 441 442 const int three_columns_layout_id = 1; 443 column_set = layout->AddColumnSet(three_columns_layout_id); 444 column_set->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 0, 445 GridLayout::USE_PREF, 0, 0); 446 column_set->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing); 447 column_set->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 0, 448 GridLayout::USE_PREF, 0, 0); 449 450 layout->StartRow(0, single_column_layout_id); 451 layout->AddView(blocked_label_, 1, 1, GridLayout::FILL, GridLayout::FILL); 452 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); 453 454 layout->StartRow(1, single_column_layout_id); 455 layout->AddView( 456 blocked_cookies_tree_->CreateParentIfNecessary(), 1, 1, 457 GridLayout::FILL, GridLayout::FILL, kTreeViewWidth, kTreeViewHeight); 458 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); 459 460 layout->StartRow(0, three_columns_layout_id); 461 layout->AddView(allow_blocked_button_); 462 layout->AddView(for_session_blocked_button_); 463 464 return pane; 465} 466 467void CollectedCookiesViews::EnableControls() { 468 bool enable_allowed_buttons = false; 469 ui::TreeModelNode* node = allowed_cookies_tree_->GetSelectedNode(); 470 if (node) { 471 CookieTreeNode* cookie_node = static_cast<CookieTreeNode*>(node); 472 if (cookie_node->GetDetailedInfo().node_type == 473 CookieTreeNode::DetailedInfo::TYPE_HOST) { 474 enable_allowed_buttons = static_cast<CookieTreeHostNode*>( 475 cookie_node)->CanCreateContentException(); 476 } 477 } 478 block_allowed_button_->SetEnabled(enable_allowed_buttons); 479 480 bool enable_blocked_buttons = false; 481 node = blocked_cookies_tree_->GetSelectedNode(); 482 if (node) { 483 CookieTreeNode* cookie_node = static_cast<CookieTreeNode*>(node); 484 if (cookie_node->GetDetailedInfo().node_type == 485 CookieTreeNode::DetailedInfo::TYPE_HOST) { 486 enable_blocked_buttons = static_cast<CookieTreeHostNode*>( 487 cookie_node)->CanCreateContentException(); 488 } 489 } 490 allow_blocked_button_->SetEnabled(enable_blocked_buttons); 491 for_session_blocked_button_->SetEnabled(enable_blocked_buttons); 492} 493 494void CollectedCookiesViews::ShowCookieInfo() { 495 ui::TreeModelNode* node = allowed_cookies_tree_->GetSelectedNode(); 496 if (!node) 497 node = blocked_cookies_tree_->GetSelectedNode(); 498 499 if (node) { 500 CookieTreeNode* cookie_node = static_cast<CookieTreeNode*>(node); 501 const CookieTreeNode::DetailedInfo detailed_info = 502 cookie_node->GetDetailedInfo(); 503 504 if (detailed_info.node_type == CookieTreeNode::DetailedInfo::TYPE_COOKIE) { 505 cookie_info_view_->SetCookie(detailed_info.cookie->Domain(), 506 *detailed_info.cookie); 507 } else { 508 cookie_info_view_->ClearCookieDisplay(); 509 } 510 } else { 511 cookie_info_view_->ClearCookieDisplay(); 512 } 513} 514 515void CollectedCookiesViews::AddContentException(views::TreeView* tree_view, 516 ContentSetting setting) { 517 CookieTreeHostNode* host_node = 518 static_cast<CookieTreeHostNode*>(tree_view->GetSelectedNode()); 519 Profile* profile = 520 Profile::FromBrowserContext(web_contents_->GetBrowserContext()); 521 host_node->CreateContentException( 522 CookieSettings::Factory::GetForProfile(profile), setting); 523 infobar_->UpdateVisibility(true, setting, host_node->GetTitle()); 524 status_changed_ = true; 525} 526 527/////////////////////////////////////////////////////////////////////////////// 528// CollectedCookiesViews, content::NotificationObserver implementation: 529 530void CollectedCookiesViews::Observe( 531 int type, 532 const content::NotificationSource& source, 533 const content::NotificationDetails& details) { 534 DCHECK_EQ(chrome::NOTIFICATION_COLLECTED_COOKIES_SHOWN, type); 535 window_->Close(); 536} 537