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/gtk/collected_cookies_gtk.h" 6 7 #include <string> 8 #include "base/prefs/pref_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/browsing_data/local_data_container.h" 18 #include "chrome/browser/chrome_notification_types.h" 19 #include "chrome/browser/content_settings/cookie_settings.h" 20 #include "chrome/browser/content_settings/local_shared_objects_container.h" 21 #include "chrome/browser/content_settings/tab_specific_content_settings.h" 22 #include "chrome/browser/infobars/infobar_service.h" 23 #include "chrome/browser/profiles/profile.h" 24 #include "chrome/browser/ui/browser_dialogs.h" 25 #include "chrome/browser/ui/collected_cookies_infobar_delegate.h" 26 #include "chrome/browser/ui/gtk/constrained_window_gtk.h" 27 #include "chrome/browser/ui/gtk/gtk_chrome_cookie_view.h" 28 #include "chrome/browser/ui/gtk/gtk_util.h" 29 #include "chrome/common/pref_names.h" 30 #include "components/web_modal/web_contents_modal_dialog_manager.h" 31 #include "content/public/browser/notification_source.h" 32 #include "content/public/browser/web_contents.h" 33 #include "content/public/browser/web_contents_view.h" 34 #include "grit/generated_resources.h" 35 #include "net/cookies/canonical_cookie.h" 36 #include "ui/base/gtk/gtk_hig_constants.h" 37 #include "ui/base/l10n/l10n_util.h" 38 39 using web_modal::WebContentsModalDialogManager; 40 41 namespace { 42 // Width and height of the cookie tree view. 43 const int kTreeViewWidth = 450; 44 const int kTreeViewHeight = 150; 45 46 // The page numbers of the pages in the notebook. 47 const gint kAllowedPageNumber = 0; 48 const gint kBlockedPageNumber = 1; 49 50 // Padding within the banner box. 51 const int kBannerPadding = 3; 52 53 // Returns the text to display in the info bar when content settings were 54 // created. 55 const std::string GetInfobarLabel(ContentSetting setting, 56 bool multiple_domains_added, 57 const base::string16& domain_name) { 58 if (multiple_domains_added) { 59 switch (setting) { 60 case CONTENT_SETTING_BLOCK: 61 return l10n_util::GetStringUTF8( 62 IDS_COLLECTED_COOKIES_MULTIPLE_BLOCK_RULES_CREATED); 63 64 case CONTENT_SETTING_ALLOW: 65 return l10n_util::GetStringUTF8( 66 IDS_COLLECTED_COOKIES_MULTIPLE_ALLOW_RULES_CREATED); 67 68 case CONTENT_SETTING_SESSION_ONLY: 69 return l10n_util::GetStringUTF8( 70 IDS_COLLECTED_COOKIES_MULTIPLE_SESSION_RULES_CREATED); 71 72 default: 73 NOTREACHED(); 74 return std::string(); 75 } 76 } 77 78 switch (setting) { 79 case CONTENT_SETTING_BLOCK: 80 return l10n_util::GetStringFUTF8( 81 IDS_COLLECTED_COOKIES_BLOCK_RULE_CREATED, domain_name); 82 83 case CONTENT_SETTING_ALLOW: 84 return l10n_util::GetStringFUTF8( 85 IDS_COLLECTED_COOKIES_ALLOW_RULE_CREATED, domain_name); 86 87 case CONTENT_SETTING_SESSION_ONLY: 88 return l10n_util::GetStringFUTF8( 89 IDS_COLLECTED_COOKIES_SESSION_RULE_CREATED, domain_name); 90 91 default: 92 NOTREACHED(); 93 return std::string(); 94 } 95 } 96 97 } // namespace 98 99 namespace chrome { 100 101 // Declared in browser_dialogs.h so others don't have to depend on our header. 102 void ShowCollectedCookiesDialog(content::WebContents* web_contents) { 103 // Deletes itself on close. 104 new CollectedCookiesGtk( 105 web_contents->GetView()->GetTopLevelNativeWindow(), 106 web_contents); 107 } 108 109 } // namespace chrome 110 111 CollectedCookiesGtk::CollectedCookiesGtk(GtkWindow* parent, 112 content::WebContents* web_contents) 113 : web_contents_(web_contents), 114 status_changed_(false) { 115 TabSpecificContentSettings* content_settings = 116 TabSpecificContentSettings::FromWebContents(web_contents); 117 registrar_.Add(this, chrome::NOTIFICATION_COLLECTED_COOKIES_SHOWN, 118 content::Source<TabSpecificContentSettings>(content_settings)); 119 120 Init(); 121 } 122 123 void CollectedCookiesGtk::Init() { 124 dialog_ = gtk_vbox_new(FALSE, ui::kContentAreaSpacing); 125 gtk_box_set_spacing(GTK_BOX(dialog_), ui::kContentAreaSpacing); 126 g_signal_connect(dialog_, "destroy", G_CALLBACK(OnDestroyThunk), this); 127 128 GtkWidget* label = gtk_label_new( 129 l10n_util::GetStringUTF8(IDS_COLLECTED_COOKIES_DIALOG_TITLE).c_str()); 130 gtk_box_pack_start(GTK_BOX(dialog_), label, TRUE, TRUE, 0); 131 132 notebook_ = gtk_notebook_new(); 133 gtk_notebook_set_tab_pos(GTK_NOTEBOOK(notebook_), GTK_POS_TOP); 134 gtk_box_pack_start(GTK_BOX(dialog_), notebook_, TRUE, TRUE, 0); 135 136 GtkWidget* allowed_pane = CreateAllowedPane(); 137 label = gtk_label_new( 138 l10n_util::GetStringUTF8(IDS_COLLECTED_COOKIES_ALLOWED_COOKIES_TAB_LABEL) 139 .c_str()); 140 gtk_widget_show(label); 141 gtk_notebook_insert_page(GTK_NOTEBOOK(notebook_), allowed_pane, label, 142 kAllowedPageNumber); 143 144 GtkWidget* blocked_pane = CreateBlockedPane(); 145 label = gtk_label_new( 146 l10n_util::GetStringUTF8(IDS_COLLECTED_COOKIES_BLOCKED_COOKIES_TAB_LABEL) 147 .c_str()); 148 gtk_widget_show(label); 149 gtk_notebook_insert_page(GTK_NOTEBOOK(notebook_), blocked_pane, label, 150 kBlockedPageNumber); 151 // Hook up the signal only after all pages are inserted, otherwise not 152 // all member variables used in OnSwitchPage() will be properly initialized. 153 g_signal_connect(notebook_, "switch-page", G_CALLBACK(OnSwitchPageThunk), 154 this); 155 156 // Cookie info view. 157 cookie_info_view_ = gtk_chrome_cookie_view_new(false); 158 gtk_box_pack_start(GTK_BOX(dialog_), cookie_info_view_, TRUE, TRUE, 0); 159 gtk_chrome_cookie_view_clear(GTK_CHROME_COOKIE_VIEW(cookie_info_view_)); 160 gtk_widget_show_all(cookie_info_view_); 161 162 // Infobar. 163 infobar_ = gtk_frame_new(NULL); 164 GtkWidget* infobar_contents = gtk_hbox_new(FALSE, kBannerPadding); 165 gtk_container_set_border_width(GTK_CONTAINER(infobar_contents), 166 kBannerPadding); 167 gtk_container_add(GTK_CONTAINER(infobar_), infobar_contents); 168 GtkWidget* info_image = 169 gtk_image_new_from_stock(GTK_STOCK_DIALOG_INFO, 170 GTK_ICON_SIZE_SMALL_TOOLBAR); 171 gtk_box_pack_start(GTK_BOX(infobar_contents), info_image, FALSE, FALSE, 0); 172 infobar_label_ = gtk_label_new(NULL); 173 gtk_box_pack_start( 174 GTK_BOX(infobar_contents), infobar_label_, FALSE, FALSE, 0); 175 gtk_widget_show_all(infobar_); 176 gtk_widget_set_no_show_all(infobar_, TRUE); 177 gtk_widget_hide(infobar_); 178 gtk_box_pack_start(GTK_BOX(dialog_), infobar_, TRUE, TRUE, 0); 179 180 // Close button. 181 GtkWidget* button_box = gtk_hbutton_box_new(); 182 gtk_button_box_set_layout(GTK_BUTTON_BOX(button_box), GTK_BUTTONBOX_END); 183 gtk_box_set_spacing(GTK_BOX(button_box), ui::kControlSpacing); 184 gtk_box_pack_end(GTK_BOX(dialog_), button_box, FALSE, TRUE, 0); 185 close_button_ = gtk_button_new_from_stock(GTK_STOCK_CLOSE); 186 gtk_button_set_label(GTK_BUTTON(close_button_), 187 l10n_util::GetStringUTF8(IDS_CLOSE).c_str()); 188 g_signal_connect(close_button_, "clicked", G_CALLBACK(OnCloseThunk), this); 189 gtk_box_pack_end(GTK_BOX(button_box), close_button_, FALSE, TRUE, 0); 190 191 // Show the dialog. 192 allowed_cookies_tree_adapter_->Init(); 193 blocked_cookies_tree_adapter_->Init(); 194 EnableControls(); 195 ShowCookieInfo(gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook_))); 196 window_ = CreateWebContentsModalDialogGtk(dialog_, close_button_); 197 198 WebContentsModalDialogManager* web_contents_modal_dialog_manager = 199 WebContentsModalDialogManager::FromWebContents(web_contents_); 200 web_contents_modal_dialog_manager->ShowDialog(window_); 201 } 202 203 GtkWidget* CollectedCookiesGtk::CreateAllowedPane() { 204 GtkWidget* cookie_list_vbox = gtk_vbox_new(FALSE, ui::kControlSpacing); 205 206 GtkWidget* label = gtk_label_new( 207 l10n_util::GetStringUTF8(IDS_COLLECTED_COOKIES_ALLOWED_COOKIES_LABEL). 208 c_str()); 209 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); 210 gtk_box_pack_start(GTK_BOX(cookie_list_vbox), label, FALSE, FALSE, 211 ui::kControlSpacing); 212 213 GtkWidget* scroll_window = gtk_scrolled_window_new(NULL, NULL); 214 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll_window), 215 GTK_POLICY_AUTOMATIC, 216 GTK_POLICY_AUTOMATIC); 217 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scroll_window), 218 GTK_SHADOW_ETCHED_IN); 219 gtk_box_pack_start(GTK_BOX(cookie_list_vbox), scroll_window, TRUE, TRUE, 0); 220 221 TabSpecificContentSettings* content_settings = 222 TabSpecificContentSettings::FromWebContents(web_contents_); 223 224 const LocalSharedObjectsContainer& allowed_data = 225 content_settings->allowed_local_shared_objects(); 226 allowed_cookies_tree_model_ = allowed_data.CreateCookiesTreeModel(); 227 228 allowed_cookies_tree_adapter_.reset( 229 new gtk_tree::TreeAdapter(this, allowed_cookies_tree_model_.get())); 230 allowed_tree_ = gtk_tree_view_new_with_model( 231 GTK_TREE_MODEL(allowed_cookies_tree_adapter_->tree_store())); 232 gtk_widget_set_size_request(allowed_tree_, kTreeViewWidth, kTreeViewHeight); 233 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(allowed_tree_), FALSE); 234 gtk_tree_view_set_enable_tree_lines(GTK_TREE_VIEW(allowed_tree_), TRUE); 235 gtk_container_add(GTK_CONTAINER(scroll_window), allowed_tree_); 236 237 GtkTreeViewColumn* title_column = gtk_tree_view_column_new(); 238 GtkCellRenderer* pixbuf_renderer = gtk_cell_renderer_pixbuf_new(); 239 gtk_tree_view_column_pack_start(title_column, pixbuf_renderer, FALSE); 240 gtk_tree_view_column_add_attribute(title_column, pixbuf_renderer, "pixbuf", 241 gtk_tree::TreeAdapter::COL_ICON); 242 GtkCellRenderer* title_renderer = gtk_cell_renderer_text_new(); 243 gtk_tree_view_column_pack_start(title_column, title_renderer, TRUE); 244 gtk_tree_view_column_add_attribute(title_column, title_renderer, "text", 245 gtk_tree::TreeAdapter::COL_TITLE); 246 gtk_tree_view_column_set_title( 247 title_column, l10n_util::GetStringUTF8( 248 IDS_COOKIES_DOMAIN_COLUMN_HEADER).c_str()); 249 gtk_tree_view_append_column(GTK_TREE_VIEW(allowed_tree_), title_column); 250 g_signal_connect(allowed_tree_, "row-expanded", 251 G_CALLBACK(OnTreeViewRowExpandedThunk), this); 252 allowed_selection_ = 253 gtk_tree_view_get_selection(GTK_TREE_VIEW(allowed_tree_)); 254 gtk_tree_selection_set_mode(allowed_selection_, GTK_SELECTION_MULTIPLE); 255 g_signal_connect(allowed_selection_, "changed", 256 G_CALLBACK(OnTreeViewSelectionChangeThunk), this); 257 258 GtkWidget* button_box = gtk_hbutton_box_new(); 259 gtk_button_box_set_layout(GTK_BUTTON_BOX(button_box), GTK_BUTTONBOX_START); 260 gtk_box_set_spacing(GTK_BOX(button_box), ui::kControlSpacing); 261 gtk_box_pack_start(GTK_BOX(cookie_list_vbox), button_box, FALSE, FALSE, 262 ui::kControlSpacing); 263 block_allowed_cookie_button_ = gtk_button_new_with_label( 264 l10n_util::GetStringUTF8(IDS_COLLECTED_COOKIES_BLOCK_BUTTON).c_str()); 265 g_signal_connect(block_allowed_cookie_button_, "clicked", 266 G_CALLBACK(OnBlockAllowedButtonClickedThunk), this); 267 gtk_container_add(GTK_CONTAINER(button_box), block_allowed_cookie_button_); 268 269 // Wrap the vbox inside an hbox so that we can specify padding along the 270 // horizontal axis. 271 GtkWidget* box = gtk_hbox_new(FALSE, 0); 272 gtk_box_pack_start(GTK_BOX(box), cookie_list_vbox, TRUE, TRUE, 273 ui::kControlSpacing); 274 return box; 275 } 276 277 GtkWidget* CollectedCookiesGtk::CreateBlockedPane() { 278 PrefService* prefs = Profile::FromBrowserContext( 279 web_contents_->GetBrowserContext())->GetPrefs(); 280 281 GtkWidget* cookie_list_vbox = gtk_vbox_new(FALSE, ui::kControlSpacing); 282 283 GtkWidget* label = gtk_label_new( 284 l10n_util::GetStringUTF8( 285 prefs->GetBoolean(prefs::kBlockThirdPartyCookies) ? 286 IDS_COLLECTED_COOKIES_BLOCKED_THIRD_PARTY_BLOCKING_ENABLED : 287 IDS_COLLECTED_COOKIES_BLOCKED_COOKIES_LABEL).c_str()); 288 gtk_widget_set_size_request(label, kTreeViewWidth, -1); 289 gtk_label_set_line_wrap(GTK_LABEL(label), TRUE); 290 gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5); 291 gtk_box_pack_start(GTK_BOX(cookie_list_vbox), label, TRUE, TRUE, 292 ui::kControlSpacing); 293 294 GtkWidget* scroll_window = gtk_scrolled_window_new(NULL, NULL); 295 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll_window), 296 GTK_POLICY_AUTOMATIC, 297 GTK_POLICY_AUTOMATIC); 298 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(scroll_window), 299 GTK_SHADOW_ETCHED_IN); 300 gtk_box_pack_start(GTK_BOX(cookie_list_vbox), scroll_window, TRUE, TRUE, 0); 301 302 TabSpecificContentSettings* content_settings = 303 TabSpecificContentSettings::FromWebContents(web_contents_); 304 305 const LocalSharedObjectsContainer& blocked_data = 306 content_settings->blocked_local_shared_objects(); 307 blocked_cookies_tree_model_ = blocked_data.CreateCookiesTreeModel(); 308 309 blocked_cookies_tree_adapter_.reset( 310 new gtk_tree::TreeAdapter(this, blocked_cookies_tree_model_.get())); 311 blocked_tree_ = gtk_tree_view_new_with_model( 312 GTK_TREE_MODEL(blocked_cookies_tree_adapter_->tree_store())); 313 gtk_widget_set_size_request(blocked_tree_, kTreeViewWidth, kTreeViewHeight); 314 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(blocked_tree_), FALSE); 315 gtk_tree_view_set_enable_tree_lines(GTK_TREE_VIEW(blocked_tree_), TRUE); 316 gtk_container_add(GTK_CONTAINER(scroll_window), blocked_tree_); 317 318 GtkTreeViewColumn* title_column = gtk_tree_view_column_new(); 319 GtkCellRenderer* pixbuf_renderer = gtk_cell_renderer_pixbuf_new(); 320 gtk_tree_view_column_pack_start(title_column, pixbuf_renderer, FALSE); 321 gtk_tree_view_column_add_attribute(title_column, pixbuf_renderer, "pixbuf", 322 gtk_tree::TreeAdapter::COL_ICON); 323 GtkCellRenderer* title_renderer = gtk_cell_renderer_text_new(); 324 gtk_tree_view_column_pack_start(title_column, title_renderer, TRUE); 325 gtk_tree_view_column_add_attribute(title_column, title_renderer, "text", 326 gtk_tree::TreeAdapter::COL_TITLE); 327 gtk_tree_view_column_set_title( 328 title_column, l10n_util::GetStringUTF8( 329 IDS_COOKIES_DOMAIN_COLUMN_HEADER).c_str()); 330 gtk_tree_view_append_column(GTK_TREE_VIEW(blocked_tree_), title_column); 331 g_signal_connect(blocked_tree_, "row-expanded", 332 G_CALLBACK(OnTreeViewRowExpandedThunk), this); 333 blocked_selection_ = 334 gtk_tree_view_get_selection(GTK_TREE_VIEW(blocked_tree_)); 335 gtk_tree_selection_set_mode(blocked_selection_, GTK_SELECTION_MULTIPLE); 336 g_signal_connect(blocked_selection_, "changed", 337 G_CALLBACK(OnTreeViewSelectionChangeThunk), this); 338 339 GtkWidget* button_box = gtk_hbutton_box_new(); 340 gtk_button_box_set_layout(GTK_BUTTON_BOX(button_box), GTK_BUTTONBOX_START); 341 gtk_box_set_spacing(GTK_BOX(button_box), ui::kControlSpacing); 342 gtk_box_pack_start(GTK_BOX(cookie_list_vbox), button_box, FALSE, FALSE, 343 ui::kControlSpacing); 344 allow_blocked_cookie_button_ = gtk_button_new_with_label( 345 l10n_util::GetStringUTF8(IDS_COLLECTED_COOKIES_ALLOW_BUTTON).c_str()); 346 g_signal_connect(allow_blocked_cookie_button_, "clicked", 347 G_CALLBACK(OnAllowBlockedButtonClickedThunk), this); 348 gtk_container_add(GTK_CONTAINER(button_box), allow_blocked_cookie_button_); 349 for_session_blocked_cookie_button_ = gtk_button_new_with_label( 350 l10n_util::GetStringUTF8(IDS_COLLECTED_COOKIES_SESSION_ONLY_BUTTON). 351 c_str()); 352 g_signal_connect(for_session_blocked_cookie_button_, "clicked", 353 G_CALLBACK(OnForSessionBlockedButtonClickedThunk), this); 354 gtk_container_add(GTK_CONTAINER(button_box), 355 for_session_blocked_cookie_button_); 356 357 // Wrap the vbox inside an hbox so that we can specify padding along the 358 // horizontal axis. 359 GtkWidget* box = gtk_hbox_new(FALSE, 0); 360 gtk_box_pack_start(GTK_BOX(box), cookie_list_vbox, TRUE, TRUE, 361 ui::kControlSpacing); 362 return box; 363 } 364 365 void CollectedCookiesGtk::ShowCookieInfo(gint current_page) { 366 if (current_page == kAllowedPageNumber) { 367 ShowSelectionInfo(allowed_selection_, allowed_cookies_tree_adapter_.get()); 368 } else if (current_page == kBlockedPageNumber) { 369 ShowSelectionInfo(blocked_selection_, blocked_cookies_tree_adapter_.get()); 370 } 371 } 372 373 void CollectedCookiesGtk::ShowSelectionInfo(GtkTreeSelection* selection, 374 gtk_tree::TreeAdapter* adapter) { 375 // Check if one "cookie" node is selected. Don't allow more than one. 376 GtkTreeModel* model; 377 GList* paths = gtk_tree_selection_get_selected_rows(selection, &model); 378 if (g_list_length(paths) == 1) { 379 GList* item = g_list_first(paths); 380 GtkTreeIter iter; 381 gtk_tree_model_get_iter(model, &iter, 382 reinterpret_cast<GtkTreePath*>(item->data)); 383 CookieTreeNode* node = 384 static_cast<CookieTreeNode*>(adapter->GetNode(&iter)); 385 const CookieTreeNode::DetailedInfo detailed_info = node->GetDetailedInfo(); 386 if (detailed_info.node_type == CookieTreeNode::DetailedInfo::TYPE_COOKIE) { 387 gtk_chrome_cookie_view_display_cookie( 388 GTK_CHROME_COOKIE_VIEW(cookie_info_view_), 389 detailed_info.cookie->Domain(), 390 *detailed_info.cookie); 391 } else { 392 gtk_chrome_cookie_view_clear(GTK_CHROME_COOKIE_VIEW(cookie_info_view_)); 393 } 394 } else { 395 gtk_chrome_cookie_view_clear(GTK_CHROME_COOKIE_VIEW(cookie_info_view_)); 396 } 397 398 g_list_foreach(paths, reinterpret_cast<GFunc>(gtk_tree_path_free), NULL); 399 g_list_free(paths); 400 } 401 402 CollectedCookiesGtk::~CollectedCookiesGtk() { 403 gtk_widget_destroy(dialog_); 404 } 405 406 bool CollectedCookiesGtk::SelectionContainsHostNode( 407 GtkTreeSelection* selection, gtk_tree::TreeAdapter* adapter) { 408 // Check whether at least one "origin" node is selected. 409 GtkTreeModel* model; 410 GList* paths = 411 gtk_tree_selection_get_selected_rows(selection, &model); 412 bool contains_host_node = false; 413 for (GList* item = paths; item; item = item->next) { 414 GtkTreeIter iter; 415 gtk_tree_model_get_iter( 416 model, &iter, reinterpret_cast<GtkTreePath*>(item->data)); 417 CookieTreeNode* node = 418 static_cast<CookieTreeNode*>(adapter->GetNode(&iter)); 419 if (node->GetDetailedInfo().node_type != 420 CookieTreeNode::DetailedInfo::TYPE_HOST) 421 continue; 422 CookieTreeHostNode* host_node = static_cast<CookieTreeHostNode*>( 423 node); 424 if (!host_node->CanCreateContentException()) 425 continue; 426 contains_host_node = true; 427 } 428 g_list_foreach(paths, reinterpret_cast<GFunc>(gtk_tree_path_free), NULL); 429 g_list_free(paths); 430 return contains_host_node; 431 } 432 433 void CollectedCookiesGtk::EnableControls() { 434 // Update button states. 435 bool enable_for_allowed_cookies = 436 SelectionContainsHostNode(allowed_selection_, 437 allowed_cookies_tree_adapter_.get()); 438 gtk_widget_set_sensitive(block_allowed_cookie_button_, 439 enable_for_allowed_cookies); 440 441 bool enable_for_blocked_cookies = 442 SelectionContainsHostNode(blocked_selection_, 443 blocked_cookies_tree_adapter_.get()); 444 gtk_widget_set_sensitive(allow_blocked_cookie_button_, 445 enable_for_blocked_cookies); 446 gtk_widget_set_sensitive(for_session_blocked_cookie_button_, 447 enable_for_blocked_cookies); 448 } 449 450 void CollectedCookiesGtk::Observe(int type, 451 const content::NotificationSource& source, 452 const content::NotificationDetails& details) { 453 DCHECK(type == chrome::NOTIFICATION_COLLECTED_COOKIES_SHOWN); 454 gtk_widget_destroy(window_); 455 } 456 457 void CollectedCookiesGtk::OnClose(GtkWidget* close_button) { 458 if (status_changed_) { 459 CollectedCookiesInfoBarDelegate::Create( 460 InfoBarService::FromWebContents(web_contents_)); 461 } 462 gtk_widget_destroy(window_); 463 } 464 465 void CollectedCookiesGtk::AddExceptions(GtkTreeSelection* selection, 466 gtk_tree::TreeAdapter* adapter, 467 ContentSetting setting) { 468 GtkTreeModel* model; 469 GList* paths = 470 gtk_tree_selection_get_selected_rows(selection, &model); 471 base::string16 last_domain_name; 472 bool multiple_domains_added = false; 473 for (GList* item = paths; item; item = item->next) { 474 GtkTreeIter iter; 475 gtk_tree_model_get_iter( 476 model, &iter, reinterpret_cast<GtkTreePath*>(item->data)); 477 CookieTreeNode* node = 478 static_cast<CookieTreeNode*>(adapter->GetNode(&iter)); 479 if (node->GetDetailedInfo().node_type != 480 CookieTreeNode::DetailedInfo::TYPE_HOST) 481 continue; 482 CookieTreeHostNode* host_node = static_cast<CookieTreeHostNode*>( 483 node); 484 if (host_node->CanCreateContentException()) { 485 if (!last_domain_name.empty()) 486 multiple_domains_added = true; 487 last_domain_name = host_node->GetTitle(); 488 Profile* profile = 489 Profile::FromBrowserContext(web_contents_->GetBrowserContext()); 490 host_node->CreateContentException( 491 CookieSettings::Factory::GetForProfile(profile).get(), setting); 492 } 493 } 494 g_list_foreach(paths, reinterpret_cast<GFunc>(gtk_tree_path_free), NULL); 495 g_list_free(paths); 496 if (last_domain_name.empty()) { 497 gtk_widget_hide(infobar_); 498 } else { 499 gtk_label_set_text( 500 GTK_LABEL(infobar_label_), GetInfobarLabel( 501 setting, multiple_domains_added, last_domain_name).c_str()); 502 gtk_widget_show(infobar_); 503 } 504 status_changed_ = true; 505 } 506 507 void CollectedCookiesGtk::OnBlockAllowedButtonClicked(GtkWidget* button) { 508 AddExceptions(allowed_selection_, allowed_cookies_tree_adapter_.get(), 509 CONTENT_SETTING_BLOCK); 510 } 511 512 void CollectedCookiesGtk::OnAllowBlockedButtonClicked(GtkWidget* button) { 513 AddExceptions(blocked_selection_, blocked_cookies_tree_adapter_.get(), 514 CONTENT_SETTING_ALLOW); 515 } 516 517 void CollectedCookiesGtk::OnForSessionBlockedButtonClicked(GtkWidget* button) { 518 AddExceptions(blocked_selection_, blocked_cookies_tree_adapter_.get(), 519 CONTENT_SETTING_SESSION_ONLY); 520 } 521 522 void CollectedCookiesGtk::OnSwitchPage(GtkWidget* notebook, 523 gpointer page, 524 guint page_num) { 525 EnableControls(); 526 ShowCookieInfo(page_num); 527 } 528 529 void CollectedCookiesGtk::OnTreeViewRowExpanded(GtkWidget* tree_view, 530 GtkTreeIter* iter, 531 GtkTreePath* path) { 532 // When a row in the tree is expanded, expand all the children too. 533 g_signal_handlers_block_by_func( 534 tree_view, reinterpret_cast<gpointer>(OnTreeViewRowExpandedThunk), this); 535 gtk_tree_view_expand_row(GTK_TREE_VIEW(tree_view), path, TRUE); 536 g_signal_handlers_unblock_by_func( 537 tree_view, reinterpret_cast<gpointer>(OnTreeViewRowExpandedThunk), this); 538 } 539 540 void CollectedCookiesGtk::OnTreeViewSelectionChange(GtkWidget* selection) { 541 EnableControls(); 542 ShowCookieInfo(gtk_notebook_get_current_page(GTK_NOTEBOOK(notebook_))); 543 } 544 545 void CollectedCookiesGtk::OnDestroy(GtkWidget* widget) { 546 delete this; 547 } 548