collected_cookies_views.cc revision ca12bfac764ba476d6cd062bf1dde12cc64c3f40
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/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/constrained_window_views.h" 24#include "chrome/browser/ui/views/cookie_info_view.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#include "ui/views/window/dialog_delegate.h" 49 50using web_modal::WebContentsModalDialogManager; 51 52namespace chrome { 53 54// Declared in browser_dialogs.h so others don't have to depend on our header. 55void ShowCollectedCookiesDialog(content::WebContents* web_contents) { 56 // Deletes itself on close. 57 new CollectedCookiesViews(web_contents); 58} 59 60} // namespace chrome 61 62namespace { 63 64// Spacing between the infobar frame and its contents. 65const int kInfobarVerticalPadding = 3; 66const int kInfobarHorizontalPadding = 8; 67 68// Width of the infobar frame. 69const int kInfobarBorderSize = 1; 70 71// Dimensions of the tree views. 72const int kTreeViewWidth = 400; 73const int kTreeViewHeight = 125; 74 75} // namespace 76 77// A custom view that conditionally displays an infobar. 78class InfobarView : public views::View { 79 public: 80 InfobarView() { 81 content_ = new views::View; 82#if defined(USE_AURA) || !defined(OS_WIN) 83 SkColor border_color = SK_ColorGRAY; 84#else 85 SkColor border_color = color_utils::GetSysSkColor(COLOR_3DSHADOW); 86#endif 87 views::Border* border = views::Border::CreateSolidBorder( 88 kInfobarBorderSize, border_color); 89 content_->set_border(border); 90 91 ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance(); 92 info_image_ = new views::ImageView(); 93 info_image_->SetImage(rb.GetImageSkiaNamed(IDR_INFO)); 94 label_ = new views::Label(); 95 } 96 virtual ~InfobarView() {} 97 98 // Update the visibility of the infobar. If |is_visible| is true, a rule for 99 // |setting| on |domain_name| was created. 100 void UpdateVisibility(bool is_visible, 101 ContentSetting setting, 102 const string16& domain_name) { 103 if (!is_visible) { 104 SetVisible(false); 105 return; 106 } 107 108 string16 label; 109 switch (setting) { 110 case CONTENT_SETTING_BLOCK: 111 label = l10n_util::GetStringFUTF16( 112 IDS_COLLECTED_COOKIES_BLOCK_RULE_CREATED, domain_name); 113 break; 114 115 case CONTENT_SETTING_ALLOW: 116 label = l10n_util::GetStringFUTF16( 117 IDS_COLLECTED_COOKIES_ALLOW_RULE_CREATED, domain_name); 118 break; 119 120 case CONTENT_SETTING_SESSION_ONLY: 121 label = l10n_util::GetStringFUTF16( 122 IDS_COLLECTED_COOKIES_SESSION_RULE_CREATED, domain_name); 123 break; 124 125 default: 126 NOTREACHED(); 127 } 128 label_->SetText(label); 129 content_->Layout(); 130 SetVisible(true); 131 } 132 133 private: 134 // Initialize contents and layout. 135 void Init() { 136 AddChildView(content_); 137 content_->SetLayoutManager( 138 new views::BoxLayout(views::BoxLayout::kHorizontal, 139 kInfobarHorizontalPadding, 140 kInfobarVerticalPadding, 141 views::kRelatedControlSmallHorizontalSpacing)); 142 content_->AddChildView(info_image_); 143 content_->AddChildView(label_); 144 UpdateVisibility(false, CONTENT_SETTING_BLOCK, string16()); 145 } 146 147 // views::View overrides. 148 virtual gfx::Size GetPreferredSize() OVERRIDE { 149 if (!visible()) 150 return gfx::Size(); 151 152 // Add space around the banner. 153 gfx::Size size(content_->GetPreferredSize()); 154 size.Enlarge(0, 2 * views::kRelatedControlVerticalSpacing); 155 return size; 156 } 157 158 virtual void Layout() OVERRIDE { 159 content_->SetBounds( 160 0, views::kRelatedControlVerticalSpacing, 161 width(), height() - views::kRelatedControlVerticalSpacing); 162 } 163 164 virtual void ViewHierarchyChanged( 165 const ViewHierarchyChangedDetails& details) OVERRIDE { 166 if (details.is_add && details.child == this) 167 Init(); 168 } 169 170 // Holds the info icon image and text label and renders the border. 171 views::View* content_; 172 // Info icon image. 173 views::ImageView* info_image_; 174 // The label responsible for rendering the text. 175 views::Label* label_; 176 177 DISALLOW_COPY_AND_ASSIGN(InfobarView); 178}; 179 180/////////////////////////////////////////////////////////////////////////////// 181// CollectedCookiesViews, public: 182 183CollectedCookiesViews::CollectedCookiesViews(content::WebContents* web_contents) 184 : web_contents_(web_contents), 185 allowed_label_(NULL), 186 blocked_label_(NULL), 187 allowed_cookies_tree_(NULL), 188 blocked_cookies_tree_(NULL), 189 block_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 WebContentsModalDialogManager* web_contents_modal_dialog_manager = 200 WebContentsModalDialogManager::FromWebContents(web_contents); 201 window_ = CreateWebContentsModalDialogViews( 202 this, 203 web_contents->GetView()->GetNativeView(), 204 web_contents_modal_dialog_manager->delegate()-> 205 GetWebContentsModalDialogHost()); 206 web_contents_modal_dialog_manager->ShowDialog(window_->GetNativeView()); 207} 208 209/////////////////////////////////////////////////////////////////////////////// 210// CollectedCookiesViews, views::DialogDelegate implementation: 211 212string16 CollectedCookiesViews::GetWindowTitle() const { 213 return l10n_util::GetStringUTF16(IDS_COLLECTED_COOKIES_DIALOG_TITLE); 214} 215 216int CollectedCookiesViews::GetDialogButtons() const { 217 return ui::DIALOG_BUTTON_CANCEL; 218} 219 220string16 CollectedCookiesViews::GetDialogButtonLabel( 221 ui::DialogButton button) const { 222 return l10n_util::GetStringUTF16(IDS_CLOSE); 223} 224 225void CollectedCookiesViews::DeleteDelegate() { 226 delete this; 227} 228 229bool CollectedCookiesViews::Cancel() { 230 if (status_changed_) { 231 CollectedCookiesInfoBarDelegate::Create( 232 InfoBarService::FromWebContents(web_contents_)); 233 } 234 235 return true; 236} 237 238// TODO(wittman): Remove this override once we move to the new style frame view 239// on all dialogs. 240views::NonClientFrameView* CollectedCookiesViews::CreateNonClientFrameView( 241 views::Widget* widget) { 242 return CreateConstrainedStyleNonClientFrameView( 243 widget, 244 web_contents_->GetBrowserContext()); 245} 246 247ui::ModalType CollectedCookiesViews::GetModalType() const { 248#if defined(USE_ASH) 249 return ui::MODAL_TYPE_CHILD; 250#else 251 return views::WidgetDelegate::GetModalType(); 252#endif 253} 254 255/////////////////////////////////////////////////////////////////////////////// 256// CollectedCookiesViews, views::ButtonListener implementation: 257 258void CollectedCookiesViews::ButtonPressed(views::Button* sender, 259 const ui::Event& event) { 260 if (sender == block_allowed_button_) 261 AddContentException(allowed_cookies_tree_, CONTENT_SETTING_BLOCK); 262 else if (sender == allow_blocked_button_) 263 AddContentException(blocked_cookies_tree_, CONTENT_SETTING_ALLOW); 264 else if (sender == for_session_blocked_button_) 265 AddContentException(blocked_cookies_tree_, CONTENT_SETTING_SESSION_ONLY); 266} 267 268/////////////////////////////////////////////////////////////////////////////// 269// CollectedCookiesViews, views::TabbedPaneListener implementation: 270 271void CollectedCookiesViews::TabSelectedAt(int index) { 272 EnableControls(); 273 ShowCookieInfo(); 274} 275 276/////////////////////////////////////////////////////////////////////////////// 277// CollectedCookiesViews, views::TreeViewController implementation: 278 279void CollectedCookiesViews::OnTreeViewSelectionChanged( 280 views::TreeView* tree_view) { 281 EnableControls(); 282 ShowCookieInfo(); 283} 284 285/////////////////////////////////////////////////////////////////////////////// 286// CollectedCookiesViews, views::View overrides: 287 288void CollectedCookiesViews::ViewHierarchyChanged( 289 const ViewHierarchyChangedDetails& details) { 290 if (details.is_add && details.child == this) 291 Init(); 292} 293 294//////////////////////////////////////////////////////////////////////////////// 295// CollectedCookiesViews, private: 296 297CollectedCookiesViews::~CollectedCookiesViews() { 298 allowed_cookies_tree_->SetModel(NULL); 299 blocked_cookies_tree_->SetModel(NULL); 300} 301 302void CollectedCookiesViews::Init() { 303 using views::GridLayout; 304 305 GridLayout* layout = GridLayout::CreatePanel(this); 306 SetLayoutManager(layout); 307 308 const int single_column_layout_id = 0; 309 views::ColumnSet* column_set = layout->AddColumnSet(single_column_layout_id); 310 column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 1, 311 GridLayout::USE_PREF, 0, 0); 312 313 layout->StartRow(0, single_column_layout_id); 314 views::TabbedPane* tabbed_pane = NULL; 315 if (DialogDelegate::UseNewStyle()) { 316 tabbed_pane = new views::TabbedPane(false); 317 layout->SetInsets(gfx::Insets()); 318 } else { 319 tabbed_pane = new views::TabbedPane(true); 320 } 321 322 layout->AddView(tabbed_pane); 323 // NOTE: Panes must be added after |tabbed_pane| has been added to its parent. 324 string16 label_allowed = l10n_util::GetStringUTF16( 325 IDS_COLLECTED_COOKIES_ALLOWED_COOKIES_TAB_LABEL); 326 string16 label_blocked = l10n_util::GetStringUTF16( 327 IDS_COLLECTED_COOKIES_BLOCKED_COOKIES_TAB_LABEL); 328 tabbed_pane->AddTab(label_allowed, CreateAllowedPane()); 329 tabbed_pane->AddTab(label_blocked, CreateBlockedPane()); 330 tabbed_pane->SelectTabAt(0); 331 tabbed_pane->set_listener(this); 332 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); 333 334 layout->StartRow(0, single_column_layout_id); 335 cookie_info_view_ = new CookieInfoView(); 336 layout->AddView(cookie_info_view_); 337 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); 338 339 layout->StartRow(0, single_column_layout_id); 340 infobar_ = new InfobarView(); 341 layout->AddView(infobar_); 342 343 EnableControls(); 344 ShowCookieInfo(); 345} 346 347views::View* CollectedCookiesViews::CreateAllowedPane() { 348 TabSpecificContentSettings* content_settings = 349 TabSpecificContentSettings::FromWebContents(web_contents_); 350 351 // Create the controls that go into the pane. 352 allowed_label_ = new views::Label(l10n_util::GetStringUTF16( 353 IDS_COLLECTED_COOKIES_ALLOWED_COOKIES_LABEL)); 354 355 const LocalSharedObjectsContainer& allowed_data = 356 content_settings->allowed_local_shared_objects(); 357 allowed_cookies_tree_model_ = allowed_data.CreateCookiesTreeModel(); 358 allowed_cookies_tree_ = new views::TreeView(); 359 allowed_cookies_tree_->SetModel(allowed_cookies_tree_model_.get()); 360 allowed_cookies_tree_->SetRootShown(false); 361 allowed_cookies_tree_->SetEditable(false); 362 allowed_cookies_tree_->set_auto_expand_children(true); 363 allowed_cookies_tree_->SetController(this); 364 365 block_allowed_button_ = new views::LabelButton(this, 366 l10n_util::GetStringUTF16(IDS_COLLECTED_COOKIES_BLOCK_BUTTON)); 367 block_allowed_button_->SetStyle(views::Button::STYLE_NATIVE_TEXTBUTTON); 368 369 // Create the view that holds all the controls together. This will be the 370 // pane added to the tabbed pane. 371 using views::GridLayout; 372 373 views::View* pane = new views::View(); 374 GridLayout* layout = GridLayout::CreatePanel(pane); 375 pane->SetLayoutManager(layout); 376 377 const int single_column_layout_id = 0; 378 views::ColumnSet* column_set = layout->AddColumnSet(single_column_layout_id); 379 column_set->AddColumn(GridLayout::LEADING, GridLayout::FILL, 1, 380 GridLayout::USE_PREF, 0, 0); 381 382 layout->StartRow(0, single_column_layout_id); 383 layout->AddView(allowed_label_); 384 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); 385 386 layout->StartRow(1, single_column_layout_id); 387 layout->AddView(allowed_cookies_tree_->CreateParentIfNecessary(), 1, 1, 388 GridLayout::FILL, GridLayout::FILL, kTreeViewWidth, 389 kTreeViewHeight); 390 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); 391 392 layout->StartRow(0, single_column_layout_id); 393 layout->AddView(block_allowed_button_, 1, 1, GridLayout::LEADING, 394 GridLayout::CENTER); 395 396 return pane; 397} 398 399views::View* CollectedCookiesViews::CreateBlockedPane() { 400 TabSpecificContentSettings* content_settings = 401 TabSpecificContentSettings::FromWebContents(web_contents_); 402 403 Profile* profile = 404 Profile::FromBrowserContext(web_contents_->GetBrowserContext()); 405 PrefService* prefs = profile->GetPrefs(); 406 407 // Create the controls that go into the pane. 408 blocked_label_ = new views::Label( 409 l10n_util::GetStringUTF16( 410 prefs->GetBoolean(prefs::kBlockThirdPartyCookies) ? 411 IDS_COLLECTED_COOKIES_BLOCKED_THIRD_PARTY_BLOCKING_ENABLED : 412 IDS_COLLECTED_COOKIES_BLOCKED_COOKIES_LABEL)); 413 blocked_label_->SetMultiLine(true); 414 blocked_label_->SetHorizontalAlignment(gfx::ALIGN_LEFT); 415 const LocalSharedObjectsContainer& blocked_data = 416 content_settings->blocked_local_shared_objects(); 417 blocked_cookies_tree_model_ = blocked_data.CreateCookiesTreeModel(); 418 blocked_cookies_tree_ = new views::TreeView(); 419 blocked_cookies_tree_->SetModel(blocked_cookies_tree_model_.get()); 420 blocked_cookies_tree_->SetRootShown(false); 421 blocked_cookies_tree_->SetEditable(false); 422 blocked_cookies_tree_->set_auto_expand_children(true); 423 blocked_cookies_tree_->SetController(this); 424 425 allow_blocked_button_ = new views::LabelButton(this, 426 l10n_util::GetStringUTF16(IDS_COLLECTED_COOKIES_ALLOW_BUTTON)); 427 allow_blocked_button_->SetStyle(views::Button::STYLE_NATIVE_TEXTBUTTON); 428 for_session_blocked_button_ = new views::LabelButton(this, 429 l10n_util::GetStringUTF16(IDS_COLLECTED_COOKIES_SESSION_ONLY_BUTTON)); 430 for_session_blocked_button_->SetStyle(views::Button::STYLE_NATIVE_TEXTBUTTON); 431 432 // Create the view that holds all the controls together. This will be the 433 // pane added to the tabbed pane. 434 using views::GridLayout; 435 436 views::View* pane = new views::View(); 437 GridLayout* layout = GridLayout::CreatePanel(pane); 438 pane->SetLayoutManager(layout); 439 440 const int single_column_layout_id = 0; 441 views::ColumnSet* column_set = layout->AddColumnSet(single_column_layout_id); 442 column_set->AddColumn(GridLayout::LEADING, GridLayout::FILL, 1, 443 GridLayout::USE_PREF, 0, 0); 444 445 const int three_columns_layout_id = 1; 446 column_set = layout->AddColumnSet(three_columns_layout_id); 447 column_set->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 0, 448 GridLayout::USE_PREF, 0, 0); 449 column_set->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing); 450 column_set->AddColumn(GridLayout::LEADING, GridLayout::CENTER, 0, 451 GridLayout::USE_PREF, 0, 0); 452 453 layout->StartRow(0, single_column_layout_id); 454 layout->AddView(blocked_label_, 1, 1, GridLayout::FILL, GridLayout::FILL); 455 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); 456 457 layout->StartRow(1, single_column_layout_id); 458 layout->AddView( 459 blocked_cookies_tree_->CreateParentIfNecessary(), 1, 1, 460 GridLayout::FILL, GridLayout::FILL, kTreeViewWidth, kTreeViewHeight); 461 layout->AddPaddingRow(0, views::kRelatedControlVerticalSpacing); 462 463 layout->StartRow(0, three_columns_layout_id); 464 layout->AddView(allow_blocked_button_); 465 layout->AddView(for_session_blocked_button_); 466 467 return pane; 468} 469 470void CollectedCookiesViews::EnableControls() { 471 bool enable_allowed_buttons = false; 472 ui::TreeModelNode* node = allowed_cookies_tree_->GetSelectedNode(); 473 if (node) { 474 CookieTreeNode* cookie_node = static_cast<CookieTreeNode*>(node); 475 if (cookie_node->GetDetailedInfo().node_type == 476 CookieTreeNode::DetailedInfo::TYPE_HOST) { 477 enable_allowed_buttons = static_cast<CookieTreeHostNode*>( 478 cookie_node)->CanCreateContentException(); 479 } 480 } 481 block_allowed_button_->SetEnabled(enable_allowed_buttons); 482 483 bool enable_blocked_buttons = false; 484 node = blocked_cookies_tree_->GetSelectedNode(); 485 if (node) { 486 CookieTreeNode* cookie_node = static_cast<CookieTreeNode*>(node); 487 if (cookie_node->GetDetailedInfo().node_type == 488 CookieTreeNode::DetailedInfo::TYPE_HOST) { 489 enable_blocked_buttons = static_cast<CookieTreeHostNode*>( 490 cookie_node)->CanCreateContentException(); 491 } 492 } 493 allow_blocked_button_->SetEnabled(enable_blocked_buttons); 494 for_session_blocked_button_->SetEnabled(enable_blocked_buttons); 495} 496 497void CollectedCookiesViews::ShowCookieInfo() { 498 ui::TreeModelNode* node = allowed_cookies_tree_->GetSelectedNode(); 499 if (!node) 500 node = blocked_cookies_tree_->GetSelectedNode(); 501 502 if (node) { 503 CookieTreeNode* cookie_node = static_cast<CookieTreeNode*>(node); 504 const CookieTreeNode::DetailedInfo detailed_info = 505 cookie_node->GetDetailedInfo(); 506 507 if (detailed_info.node_type == CookieTreeNode::DetailedInfo::TYPE_COOKIE) { 508 cookie_info_view_->SetCookie(detailed_info.cookie->Domain(), 509 *detailed_info.cookie); 510 } else { 511 cookie_info_view_->ClearCookieDisplay(); 512 } 513 } else { 514 cookie_info_view_->ClearCookieDisplay(); 515 } 516} 517 518void CollectedCookiesViews::AddContentException(views::TreeView* tree_view, 519 ContentSetting setting) { 520 CookieTreeHostNode* host_node = 521 static_cast<CookieTreeHostNode*>(tree_view->GetSelectedNode()); 522 Profile* profile = 523 Profile::FromBrowserContext(web_contents_->GetBrowserContext()); 524 host_node->CreateContentException( 525 CookieSettings::Factory::GetForProfile(profile).get(), setting); 526 infobar_->UpdateVisibility(true, setting, host_node->GetTitle()); 527 status_changed_ = true; 528} 529 530/////////////////////////////////////////////////////////////////////////////// 531// CollectedCookiesViews, content::NotificationObserver implementation: 532 533void CollectedCookiesViews::Observe( 534 int type, 535 const content::NotificationSource& source, 536 const content::NotificationDetails& details) { 537 DCHECK_EQ(chrome::NOTIFICATION_COLLECTED_COOKIES_SHOWN, type); 538 window_->Close(); 539} 540