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