diff options
author | mattm@chromium.org <mattm@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-11-30 22:41:36 +0000 |
---|---|---|
committer | mattm@chromium.org <mattm@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-11-30 22:41:36 +0000 |
commit | 33964ca57ee7192ca32aea0e63dca8e825305206 (patch) | |
tree | 7029f512a3ac730261c4ed54aed935b6b9defbae /chrome/browser/gtk | |
parent | 52c27fbc951fb7b98ae912944419bc5873e5721f (diff) | |
download | chromium_src-33964ca57ee7192ca32aea0e63dca8e825305206.zip chromium_src-33964ca57ee7192ca32aea0e63dca8e825305206.tar.gz chromium_src-33964ca57ee7192ca32aea0e63dca8e825305206.tar.bz2 |
Linux: Adds back the ability to filter cookies by origin in the cookies options view
BUG=27657
TEST=unittest passes, manually testing typing "google" in the search field pulls up origins containing "google" in their name
Review URL: http://codereview.chromium.org/437075
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@33359 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/gtk')
-rw-r--r-- | chrome/browser/gtk/options/cookies_view.cc | 75 | ||||
-rw-r--r-- | chrome/browser/gtk/options/cookies_view.h | 21 | ||||
-rw-r--r-- | chrome/browser/gtk/options/cookies_view_unittest.cc | 183 |
3 files changed, 273 insertions, 6 deletions
diff --git a/chrome/browser/gtk/options/cookies_view.cc b/chrome/browser/gtk/options/cookies_view.cc index 02b61e6..b591cf0b 100644 --- a/chrome/browser/gtk/options/cookies_view.cc +++ b/chrome/browser/gtk/options/cookies_view.cc @@ -23,6 +23,9 @@ namespace { const int kDialogDefaultWidth = 550; const int kDialogDefaultHeight = 550; +// Delay after entering filter text before filtering occurs. +const int kSearchFilterDelayMs = 500; + // Response ids for our custom buttons. enum { RESPONSE_REMOVE = 1, @@ -67,7 +70,8 @@ void CookiesView::Show(Profile* profile) { } CookiesView::CookiesView(Profile* profile) - : profile_(profile) { + : profile_(profile), + filter_update_factory_(this) { Init(); } @@ -113,6 +117,29 @@ void CookiesView::Init() { g_signal_connect(dialog_, "response", G_CALLBACK(OnResponse), this); g_signal_connect(dialog_, "destroy", G_CALLBACK(OnWindowDestroy), this); + // Filtering controls. + GtkWidget* filter_hbox = gtk_hbox_new(FALSE, gtk_util::kControlSpacing); + filter_entry_ = gtk_entry_new(); + g_signal_connect(G_OBJECT(filter_entry_), "activate", + G_CALLBACK(OnFilterEntryActivated), this); + g_signal_connect(G_OBJECT(filter_entry_), "changed", + G_CALLBACK(OnFilterEntryChanged), this); + gtk_box_pack_start(GTK_BOX(filter_hbox), filter_entry_, + TRUE, TRUE, 0); + filter_clear_button_ = gtk_button_new_with_mnemonic( + gtk_util::ConvertAcceleratorsFromWindowsStyle( + l10n_util::GetStringUTF8(IDS_COOKIES_CLEAR_SEARCH_LABEL)).c_str()); + g_signal_connect(G_OBJECT(filter_clear_button_), "clicked", + G_CALLBACK(OnFilterClearButtonClicked), this); + gtk_box_pack_start(GTK_BOX(filter_hbox), filter_clear_button_, + FALSE, FALSE, 0); + + GtkWidget* filter_controls = gtk_util::CreateLabeledControlsGroup(NULL, + l10n_util::GetStringUTF8(IDS_COOKIES_SEARCH_LABEL).c_str(), filter_hbox, + NULL); + gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog_)->vbox), filter_controls, + FALSE, FALSE, 0); + // Cookie list. GtkWidget* cookie_list_vbox = gtk_vbox_new(FALSE, gtk_util::kControlSpacing); gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog_)->vbox), cookie_list_vbox, @@ -189,11 +216,8 @@ void CookiesView::Init() { // Populate the view. cookies_tree_adapter_->Init(); - gtk_tree_view_expand_all(GTK_TREE_VIEW(tree_)); + SetInitialTreeState(); EnableControls(); - - if (cookies_tree_model_->GetChildCount(cookies_tree_model_->GetRoot())) - gtk_tree::SelectAndFocusRowNum(0, GTK_TREE_VIEW(tree_)); } void CookiesView::InitStylesAndShow() { @@ -230,6 +254,12 @@ void CookiesView::InitCookieDetailRow(int row, int label_id, 1, 2, row, row + 1); } +void CookiesView::SetInitialTreeState() { + gtk_tree_view_expand_all(GTK_TREE_VIEW(tree_)); + if (cookies_tree_model_->GetChildCount(cookies_tree_model_->GetRoot())) + gtk_tree::SelectAndFocusRowNum(0, GTK_TREE_VIEW(tree_)); +} + void CookiesView::EnableControls() { GtkTreeIter iter; bool selected = gtk_tree_selection_get_selected(selection_, NULL, &iter); @@ -238,6 +268,9 @@ void CookiesView::EnableControls() { remove_all_button_, cookies_tree_model_->GetChildCount(cookies_tree_model_->GetRoot())); + const gchar* filter_text = gtk_entry_get_text(GTK_ENTRY(filter_entry_)); + gtk_widget_set_sensitive(filter_clear_button_, filter_text && *filter_text); + if (selected) { CookieTreeNode::DetailedInfo detailed_info = static_cast<CookieTreeNode*>( @@ -377,3 +410,35 @@ gboolean CookiesView::OnTreeViewKeyPress( } return FALSE; } + +void CookiesView::UpdateFilterResults() { + const gchar* text = gtk_entry_get_text(GTK_ENTRY(filter_entry_)); + if (text) { + cookies_tree_model_->UpdateSearchResults(UTF8ToWide(text)); + SetInitialTreeState(); + } +} + +// static +void CookiesView::OnFilterEntryActivated(GtkEntry* entry, CookiesView* window) { + window->filter_update_factory_.RevokeAll(); + window->UpdateFilterResults(); +} + +// static +void CookiesView::OnFilterEntryChanged(GtkEditable* editable, + CookiesView* window) { + window->filter_update_factory_.RevokeAll(); + MessageLoop::current()->PostDelayedTask(FROM_HERE, + window->filter_update_factory_.NewRunnableMethod( + &CookiesView::UpdateFilterResults), kSearchFilterDelayMs); + window->EnableControls(); +} + +// static +void CookiesView::OnFilterClearButtonClicked(GtkButton* button, + CookiesView* window) { + gtk_entry_set_text(GTK_ENTRY(window->filter_entry_), ""); + window->filter_update_factory_.RevokeAll(); + window->UpdateFilterResults(); +} diff --git a/chrome/browser/gtk/options/cookies_view.h b/chrome/browser/gtk/options/cookies_view.h index dea3da2..1d63c48 100644 --- a/chrome/browser/gtk/options/cookies_view.h +++ b/chrome/browser/gtk/options/cookies_view.h @@ -49,6 +49,9 @@ class CookiesView : public gtk_tree::TreeAdapter::Delegate { // Helper for initializing cookie details table. void InitCookieDetailRow(int row, int label_id, GtkWidget** display_label); + // Set the initial selection and tree expanded state. + void SetInitialTreeState(); + // Set sensitivity of buttons based on selection and filter state. void EnableControls(); @@ -80,11 +83,22 @@ class CookiesView : public gtk_tree::TreeAdapter::Delegate { static gboolean OnTreeViewKeyPress(GtkWidget* tree_view, GdkEventKey* key, CookiesView* window); + // Filter the list against the text in |filter_entry_|. + void UpdateFilterResults(); + + // Callbacks for user actions filtering the list. + static void OnFilterEntryActivated(GtkEntry* entry, CookiesView* window); + static void OnFilterEntryChanged(GtkEditable* editable, CookiesView* window); + static void OnFilterClearButtonClicked(GtkButton* button, + CookiesView* window); + // The parent widget. GtkWidget* dialog_; // Widgets of the dialog. GtkWidget* description_label_; + GtkWidget* filter_entry_; + GtkWidget* filter_clear_button_; GtkWidget* remove_button_; GtkWidget* remove_all_button_; @@ -105,6 +119,10 @@ class CookiesView : public gtk_tree::TreeAdapter::Delegate { // The profile. Profile* profile_; + // A factory to construct Runnable Methods so that we can be called back to + // re-evaluate the model after the search query string changes. + ScopedRunnableMethodFactory<CookiesView> filter_update_factory_; + // The Cookies Table model. scoped_ptr<CookiesTreeModel> cookies_tree_model_; scoped_ptr<gtk_tree::TreeAdapter> cookies_tree_adapter_; @@ -118,6 +136,9 @@ class CookiesView : public gtk_tree::TreeAdapter::Delegate { FRIEND_TEST(CookiesViewTest, RemoveCookiesByDomain); FRIEND_TEST(CookiesViewTest, RemoveByDomain); FRIEND_TEST(CookiesViewTest, RemoveDefaultSelection); + FRIEND_TEST(CookiesViewTest, Filter); + FRIEND_TEST(CookiesViewTest, FilterRemoveAll); + FRIEND_TEST(CookiesViewTest, FilterRemove); DISALLOW_COPY_AND_ASSIGN(CookiesView); }; diff --git a/chrome/browser/gtk/options/cookies_view_unittest.cc b/chrome/browser/gtk/options/cookies_view_unittest.cc index 2160bfa..a81e11a 100644 --- a/chrome/browser/gtk/options/cookies_view_unittest.cc +++ b/chrome/browser/gtk/options/cookies_view_unittest.cc @@ -137,8 +137,10 @@ class CookiesViewTest : public testing::Test { if (!path) return false; gtk_tree_selection_select_path(cookies_view.selection_, path); + bool rv = gtk_tree_selection_path_is_selected(cookies_view.selection_, + path); gtk_tree_path_free(path); - return true; + return rv; } std::string GetSelectedPath(const CookiesView& cookies_view) { @@ -463,3 +465,182 @@ TEST_F(CookiesViewTest, RemoveDefaultSelection) { EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_)); EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_)); } + +TEST_F(CookiesViewTest, Filter) { + net::CookieMonster* monster = profile_->GetCookieMonster(); + monster->SetCookie(GURL("http://foo0"), "C=1"); + monster->SetCookie(GURL("http://bar0"), "D=1"); + monster->SetCookie(GURL("http://foo1"), "B=1"); + monster->SetCookie(GURL("http://bar1"), "A=1"); + CookiesView cookies_view(profile_.get()); + EXPECT_STREQ("bar0,_Cookies,__D," + "bar1,_Cookies,__A," + "foo0,_Cookies,__C," + "foo1,_Cookies,__B", + GetDisplayedCookies(cookies_view).c_str()); + + EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(cookies_view.filter_clear_button_)); + + gtk_entry_set_text(GTK_ENTRY(cookies_view.filter_entry_), "bar"); + EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.filter_clear_button_)); + // Entering text doesn't immediately filter the results. + EXPECT_STREQ("bar0,_Cookies,__D," + "bar1,_Cookies,__A," + "foo0,_Cookies,__C," + "foo1,_Cookies,__B", + GetDisplayedCookies(cookies_view).c_str()); + + // Results are filtered immediately if you activate (hit enter in the entry). + gtk_widget_activate(cookies_view.filter_entry_); + EXPECT_STREQ("bar0,_Cookies,__D," + "bar1,_Cookies,__A", + GetDisplayedCookies(cookies_view).c_str()); + + gtk_button_clicked(GTK_BUTTON(cookies_view.filter_clear_button_)); + EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(cookies_view.filter_clear_button_)); + EXPECT_STREQ("", gtk_entry_get_text(GTK_ENTRY(cookies_view.filter_entry_))); + EXPECT_STREQ("bar0,_Cookies,__D," + "bar1,_Cookies,__A," + "foo0,_Cookies,__C," + "foo1,_Cookies,__B", + GetDisplayedCookies(cookies_view).c_str()); +} + +TEST_F(CookiesViewTest, FilterRemoveAll) { + net::CookieMonster* monster = profile_->GetCookieMonster(); + monster->SetCookie(GURL("http://foo0"), "C=1"); + monster->SetCookie(GURL("http://bar0"), "D=1"); + monster->SetCookie(GURL("http://foo1"), "B=1"); + monster->SetCookie(GURL("http://bar1"), "A=1"); + CookiesView cookies_view(profile_.get()); + EXPECT_STREQ("bar0,_Cookies,__D," + "bar1,_Cookies,__A," + "foo0,_Cookies,__C," + "foo1,_Cookies,__B", + GetDisplayedCookies(cookies_view).c_str()); + + EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(cookies_view.filter_clear_button_)); + + gtk_entry_set_text(GTK_ENTRY(cookies_view.filter_entry_), "bar"); + EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.filter_clear_button_)); + // Entering text doesn't immediately filter the results. + EXPECT_STREQ("bar0,_Cookies,__D," + "bar1,_Cookies,__A," + "foo0,_Cookies,__C," + "foo1,_Cookies,__B", + GetDisplayedCookies(cookies_view).c_str()); + + // Results are filtered immediately if you activate (hit enter in the entry). + gtk_widget_activate(cookies_view.filter_entry_); + EXPECT_STREQ("bar0,_Cookies,__D," + "bar1,_Cookies,__A", + GetDisplayedCookies(cookies_view).c_str()); + EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_)); + + gtk_button_clicked(GTK_BUTTON(cookies_view.remove_all_button_)); + + EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_)); + EXPECT_STREQ("", + GetDisplayedCookies(cookies_view).c_str()); + EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.filter_clear_button_)); + + gtk_button_clicked(GTK_BUTTON(cookies_view.filter_clear_button_)); + EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(cookies_view.filter_clear_button_)); + EXPECT_STREQ("", gtk_entry_get_text(GTK_ENTRY(cookies_view.filter_entry_))); + EXPECT_STREQ("foo0,_Cookies,__C," + "foo1,_Cookies,__B", + GetDisplayedCookies(cookies_view).c_str()); +} + +TEST_F(CookiesViewTest, FilterRemove) { + net::CookieMonster* monster = profile_->GetCookieMonster(); + monster->SetCookie(GURL("http://foo0"), "C=1"); + monster->SetCookie(GURL("http://bar0"), "D=1"); + monster->SetCookie(GURL("http://foo1"), "B=1"); + monster->SetCookie(GURL("http://bar1"), "A=1"); + monster->SetCookie(GURL("http://bar1"), "E=1"); + CookiesView cookies_view(profile_.get()); + EXPECT_STREQ("bar0,_Cookies,__D," + "bar1,_Cookies,__A,__E," + "foo0,_Cookies,__C," + "foo1,_Cookies,__B", + GetDisplayedCookies(cookies_view).c_str()); + EXPECT_STREQ("D,A,E,C,B", GetMonsterCookies(monster).c_str()); + + EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(cookies_view.filter_clear_button_)); + + gtk_entry_set_text(GTK_ENTRY(cookies_view.filter_entry_), "bar"); + EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.filter_clear_button_)); + // Entering text doesn't immediately filter the results. + EXPECT_STREQ("bar0,_Cookies,__D," + "bar1,_Cookies,__A,__E," + "foo0,_Cookies,__C," + "foo1,_Cookies,__B", + GetDisplayedCookies(cookies_view).c_str()); + + // Results are filtered immediately if you activate (hit enter in the entry). + gtk_widget_activate(cookies_view.filter_entry_); + EXPECT_STREQ("bar0,_Cookies,__D," + "bar1,_Cookies,__A,__E", + GetDisplayedCookies(cookies_view).c_str()); + + ASSERT_TRUE(SelectByPath(cookies_view, "1:0:0")); + + { + SCOPED_TRACE("First selection"); + EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_)); + EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_)); + CheckDetailsSensitivity(TRUE, cookies_view); + } + + gtk_button_clicked(GTK_BUTTON(cookies_view.remove_button_)); + + { + SCOPED_TRACE("First selection removed"); + EXPECT_STREQ("D,E,C,B", GetMonsterCookies(monster).c_str()); + EXPECT_STREQ("bar0,_Cookies,__D," + "bar1,_Cookies,__E", + GetDisplayedCookies(cookies_view).c_str()); + EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_)); + EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_)); + EXPECT_STREQ("1:0:0", GetSelectedPath(cookies_view).c_str()); + CheckDetailsSensitivity(TRUE, cookies_view); + } + + gtk_button_clicked(GTK_BUTTON(cookies_view.remove_button_)); + + { + SCOPED_TRACE("Second selection"); + EXPECT_STREQ("D,C,B", GetMonsterCookies(monster).c_str()); + EXPECT_STREQ("bar0,_Cookies,__D," + "bar1,_Cookies", + GetDisplayedCookies(cookies_view).c_str()); + EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_)); + EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_)); + EXPECT_STREQ("1:0", GetSelectedPath(cookies_view).c_str()); + CheckDetailsSensitivity(FALSE, cookies_view); + } + + ASSERT_TRUE(SelectByPath(cookies_view, "0:0:0")); + EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_)); + gtk_button_clicked(GTK_BUTTON(cookies_view.remove_button_)); + + { + SCOPED_TRACE("Second selection removed"); + EXPECT_STREQ("C,B", GetMonsterCookies(monster).c_str()); + EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_all_button_)); + EXPECT_EQ(TRUE, GTK_WIDGET_SENSITIVE(cookies_view.remove_button_)); + EXPECT_STREQ("0:0", GetSelectedPath(cookies_view).c_str()); + CheckDetailsSensitivity(FALSE, cookies_view); + EXPECT_STREQ("bar0,_Cookies," + "bar1,_Cookies", + GetDisplayedCookies(cookies_view).c_str()); + } + + gtk_button_clicked(GTK_BUTTON(cookies_view.filter_clear_button_)); + EXPECT_EQ(FALSE, GTK_WIDGET_SENSITIVE(cookies_view.filter_clear_button_)); + EXPECT_STREQ("", gtk_entry_get_text(GTK_ENTRY(cookies_view.filter_entry_))); + EXPECT_STREQ("foo0,_Cookies,__C," + "foo1,_Cookies,__B", + GetDisplayedCookies(cookies_view).c_str()); +} |