diff options
author | sky@chromium.org <sky@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-10-08 20:56:54 +0000 |
---|---|---|
committer | sky@chromium.org <sky@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-10-08 20:56:54 +0000 |
commit | b3ac5c830a92eecabb94160169e72415d59a5509 (patch) | |
tree | 516d1fe562c060b0a6a04a2796c3909b2646b601 | |
parent | 378c3fdf56d3f6328632f0e994a678c9387c78d3 (diff) | |
download | chromium_src-b3ac5c830a92eecabb94160169e72415d59a5509.zip chromium_src-b3ac5c830a92eecabb94160169e72415d59a5509.tar.gz chromium_src-b3ac5c830a92eecabb94160169e72415d59a5509.tar.bz2 |
Adds the ability to create a bookmark folder populated with a bookmark
for each open tab. I've currently wired this up on windows, will wire
up rest of platforms in a separate cl.
BUG=2935
TEST=on Windows open multiple tabs, right click on a tab and choose
'Bookmark all tabs'. You should then get the bookmark editor with no
url field. Accepting the dialog should result in creating a new folder
with a bookmark for each of the open tabs.
Review URL: http://codereview.chromium.org/270021
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@28446 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/app/generated_resources.grd | 6 | ||||
-rw-r--r-- | chrome/browser/bookmarks/bookmark_editor.h | 11 | ||||
-rw-r--r-- | chrome/browser/bookmarks/bookmark_utils.cc | 37 | ||||
-rw-r--r-- | chrome/browser/bookmarks/bookmark_utils.h | 13 | ||||
-rw-r--r-- | chrome/browser/browser.cc | 22 | ||||
-rw-r--r-- | chrome/browser/browser.h | 1 | ||||
-rw-r--r-- | chrome/browser/cocoa/tab_strip_controller_unittest.mm | 4 | ||||
-rw-r--r-- | chrome/browser/tabs/tab_strip_model.cc | 14 | ||||
-rw-r--r-- | chrome/browser/tabs/tab_strip_model.h | 4 | ||||
-rw-r--r-- | chrome/browser/tabs/tab_strip_model_unittest.cc | 1 | ||||
-rw-r--r-- | chrome/browser/views/bookmark_editor_view.cc | 30 | ||||
-rw-r--r-- | chrome/browser/views/bookmark_editor_view.h | 60 | ||||
-rw-r--r-- | chrome/browser/views/bookmark_editor_view_unittest.cc | 174 | ||||
-rw-r--r-- | chrome/browser/views/tabs/tab.cc | 10 |
14 files changed, 290 insertions, 97 deletions
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd index 015f683..528d447 100644 --- a/chrome/app/generated_resources.grd +++ b/chrome/app/generated_resources.grd @@ -3279,6 +3279,9 @@ Keep your key file in a safe place. You will need it to create new versions of y <message name="IDS_TAB_CXMENU_PIN_TAB" desc="The label of the tab context menu item for pinning a tab."> Pin tab </message> + <message name="IDS_TAB_CXMENU_BOOKMARK_ALL_TABS" desc="In Title Case: The label of the tab context menu item for creating a bookmark folder containing an entry for each open tab."> + Bookmark all tabs... + </message> </if> <if expr="pp_ifdef('use_titlecase')"> <message name="IDS_TAB_CXMENU_NEWTAB" desc="In Title Case: The label of the 'New Tab' Tab context menu item."> @@ -3305,6 +3308,9 @@ Keep your key file in a safe place. You will need it to create new versions of y <message name="IDS_TAB_CXMENU_PIN_TAB" desc="In Title Case: The label of the tab context menu item for pinning a tab."> Pin Tab </message> + <message name="IDS_TAB_CXMENU_BOOKMARK_ALL_TABS" desc="In Title Case: The label of the tab context menu item for creating a bookmark folder containing an entry for each open tab."> + Bookmark All Tabs... + </message> </if> <!-- Items in the bookmarks destination mode --> diff --git a/chrome/browser/bookmarks/bookmark_editor.h b/chrome/browser/bookmarks/bookmark_editor.h index b7dc15b..982c314 100644 --- a/chrome/browser/bookmarks/bookmark_editor.h +++ b/chrome/browser/bookmarks/bookmark_editor.h @@ -28,9 +28,14 @@ class BookmarkEditor { NO_TREE }; - // Shows the platform specific BookmarkEditor subclass editing |node|. If - // |node| is NULL a new entry is created initially parented to |parent|. If - // |show_tree| is false the tree is not shown. BookmarkEditor takes + // Shows the platform specific BookmarkEditor subclass editing |node|. |node| + // may be one of three values: + // . NULL, in which a case a new entry is created initially parented to + // |parent|. + // . non-null and a url. + // . non-null and a folder. In this case the url field is not shown and an + // entry for the node is not shown in the tree. + // If |show_tree| is false the tree is not shown. BookmarkEditor takes // ownership of |handler| and deletes it when done. |handler| may be // null. See description of Handler for details. static void Show(gfx::NativeView parent_window, diff --git a/chrome/browser/bookmarks/bookmark_utils.cc b/chrome/browser/bookmarks/bookmark_utils.cc index 945e22a..95cfe64 100644 --- a/chrome/browser/bookmarks/bookmark_utils.cc +++ b/chrome/browser/bookmarks/bookmark_utils.cc @@ -549,14 +549,14 @@ const BookmarkNode* ApplyEditsWithPossibleGroupChange(BookmarkModel* model, Time date_added = node->date_added(); if (new_parent == node->GetParent()) { // The parent is the same. - if (new_url != node->GetURL()) { + if (node->is_url() && new_url != node->GetURL()) { model->Remove(old_parent, old_index); return_node = model->AddURLWithCreationTime(old_parent, old_index, new_title, new_url, date_added); } else { model->SetTitle(node, new_title); } - } else if (new_url != node->GetURL()) { + } else if (node->is_url() && new_url != node->GetURL()) { // The parent and URL changed. model->Remove(old_parent, old_index); return_node = model->AddURLWithCreationTime(new_parent, @@ -594,13 +594,11 @@ void ToggleWhenVisible(Profile* profile) { NotificationService::NoDetails()); } -// static void RegisterPrefs(PrefService* prefs) { prefs->RegisterDictionaryPref(prefs::kBookmarkManagerPlacement); prefs->RegisterIntegerPref(prefs::kBookmarkManagerSplitLocation, -1); } -// static void RegisterUserPrefs(PrefService* prefs) { // Formerly in BookmarkBarView prefs->RegisterBooleanPref(prefs::kShowBookmarkBar, false); @@ -613,4 +611,35 @@ void RegisterUserPrefs(PrefService* prefs) { prefs->RegisterIntegerPref(prefs::kBookmarkTablePathWidth, -1); } +bool GetURLAndTitleToBookmark(TabContents* tab_contents, + GURL* url, + std::wstring* title) { + if (!tab_contents->ShouldDisplayURL()) + return false; + *url = tab_contents->GetURL(); + if (url->is_empty() || !url->is_valid()) + return false; + *title = UTF16ToWideHack(tab_contents->GetTitle()); + return true; +} + +const BookmarkNode* CreateBookmarkForAllTabs(Browser* browser) { + BookmarkModel* model = browser->profile()->GetBookmarkModel(); + if (!model || !model->IsLoaded()) + return NULL; + + const BookmarkNode* parent = model->GetParentForNewNodes(); + const BookmarkNode* folder = model->AddGroup( + parent, parent->GetChildCount(), + l10n_util::GetString(IDS_BOOMARK_EDITOR_NEW_FOLDER_NAME)); + for (int i = 0; i < browser->tab_count(); ++i) { + GURL url; + std::wstring title; + if (GetURLAndTitleToBookmark(browser->GetTabContentsAt(i), &url, &title)) { + model->AddURL(folder, folder->GetChildCount(), title, url); + } + } + return folder; +} + } // namespace bookmark_utils diff --git a/chrome/browser/bookmarks/bookmark_utils.h b/chrome/browser/bookmarks/bookmark_utils.h index 0c4ecab..d45ecad 100644 --- a/chrome/browser/bookmarks/bookmark_utils.h +++ b/chrome/browser/bookmarks/bookmark_utils.h @@ -16,9 +16,11 @@ class BookmarkModel; class BookmarkNode; +class Browser; class PageNavigator; class PrefService; class Profile; +class TabContents; namespace views { class DropTargetEvent; @@ -180,6 +182,17 @@ void RegisterPrefs(PrefService* prefs); // Register user prefs for BookmarkBar, BookmarkView, ... void RegisterUserPrefs(PrefService* prefs); +// Gets the url and title to use in creating a bookmark for the specified +// TabContents. Returns false if a bookmark shouldn't be created for the +// specified TabContents. +bool GetURLAndTitleToBookmark(TabContents* tab_contents, + GURL* url, + std::wstring* title); + +// Creates a new folder containing a bookmark for each of the tabs in +// |browser|. This returns null if the bookmark model isn't loaded. +const BookmarkNode* CreateBookmarkForAllTabs(Browser* browser); + // Number of bookmarks we'll open before prompting the user to see if they // really want to open all. // diff --git a/chrome/browser/browser.cc b/chrome/browser/browser.cc index 0aa1e2b..27ad096 100644 --- a/chrome/browser/browser.cc +++ b/chrome/browser/browser.cc @@ -13,6 +13,7 @@ #include "base/thread.h" #include "chrome/app/chrome_dll_resource.h" #include "chrome/browser/bookmarks/bookmark_model.h" +#include "chrome/browser/bookmarks/bookmark_utils.h" #include "chrome/browser/browser_list.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/browser_shutdown.h" @@ -897,12 +898,10 @@ void Browser::BookmarkCurrentPage() { UserMetrics::RecordAction(L"Star", profile_); TabContents* contents = GetSelectedTabContents(); - if (!contents->ShouldDisplayURL()) - return; - const GURL& url = contents->GetURL(); - if (url.is_empty() || !url.is_valid()) + GURL url; + std::wstring title; + if (!bookmark_utils::GetURLAndTitleToBookmark(contents, &url, &title)) return; - std::wstring title = UTF16ToWideHack(contents->GetTitle()); BookmarkModel* model = contents->profile()->GetBookmarkModel(); if (!model || !model->IsLoaded()) @@ -1680,6 +1679,19 @@ bool Browser::CanCloseContentsAt(int index) { return CanCloseWithInProgressDownloads(); } +void Browser::BookmarkAllTabs() { + const BookmarkNode* node = bookmark_utils::CreateBookmarkForAllTabs(this); + if (!node) + return; + + // TODO(sky): BookmarkEditor::Show should take a NativeWindow, not view. +#if defined(OS_WIN) + BookmarkEditor::Show(window()->GetNativeHandle(), profile_, + node->GetParent(), node, BookmarkEditor::SHOW_TREE, + NULL); +#endif +} + /////////////////////////////////////////////////////////////////////////////// // Browser, TabStripModelObserver implementation: diff --git a/chrome/browser/browser.h b/chrome/browser/browser.h index 646f559..d176b1d 100644 --- a/chrome/browser/browser.h +++ b/chrome/browser/browser.h @@ -474,6 +474,7 @@ class Browser : public TabStripModelDelegate, virtual void CreateHistoricalTab(TabContents* contents); virtual bool RunUnloadListenerBeforeClosing(TabContents* contents); virtual bool CanCloseContentsAt(int index); + virtual void BookmarkAllTabs(); // Overridden from TabStripModelObserver: virtual void TabInsertedAt(TabContents* contents, diff --git a/chrome/browser/cocoa/tab_strip_controller_unittest.mm b/chrome/browser/cocoa/tab_strip_controller_unittest.mm index 9d71eb3..bcc2cf8 100644 --- a/chrome/browser/cocoa/tab_strip_controller_unittest.mm +++ b/chrome/browser/cocoa/tab_strip_controller_unittest.mm @@ -53,9 +53,11 @@ class TestTabStripDelegate : public TabStripModelDelegate { virtual bool CanRestoreTab() { return true; } - virtual void RestoreTab() { } + virtual void RestoreTab() {} virtual bool CanCloseContentsAt(int index) { return true; } + + virtual void BookmarkAllTabs() {} }; class TabStripControllerTest : public PlatformTest { diff --git a/chrome/browser/tabs/tab_strip_model.cc b/chrome/browser/tabs/tab_strip_model.cc index b356c62..9ceb6d8 100644 --- a/chrome/browser/tabs/tab_strip_model.cc +++ b/chrome/browser/tabs/tab_strip_model.cc @@ -10,6 +10,7 @@ #include "base/stl_util-inl.h" #include "base/string_util.h" #include "build/build_config.h" +#include "chrome/browser/bookmarks/bookmark_model.h" #include "chrome/browser/browser_shutdown.h" #include "chrome/browser/metrics/user_metrics.h" #include "chrome/browser/profile.h" @@ -486,6 +487,12 @@ bool TabStripModel::IsContextMenuCommandEnabled( return delegate_->CanRestoreTab(); case CommandTogglePinned: return true; + case CommandBookmarkAllTabs: { + if (count() <= 1) + return false; + BookmarkModel* model = profile_->GetBookmarkModel(); + return model && model->IsLoaded(); + } default: NOTREACHED(); } @@ -550,6 +557,13 @@ void TabStripModel::ExecuteContextMenuCommand( SetTabPinned(context_index, !IsTabPinned(context_index)); break; } + + case CommandBookmarkAllTabs: { + UserMetrics::RecordAction(L"TabContextMenu_BookmarkAllTabs", profile_); + + delegate_->BookmarkAllTabs(); + break; + } default: NOTREACHED(); } diff --git a/chrome/browser/tabs/tab_strip_model.h b/chrome/browser/tabs/tab_strip_model.h index cbf23a7..9e7659e 100644 --- a/chrome/browser/tabs/tab_strip_model.h +++ b/chrome/browser/tabs/tab_strip_model.h @@ -199,6 +199,9 @@ class TabStripModelDelegate { // Returns whether some contents can be closed. virtual bool CanCloseContentsAt(int index) = 0; + + // Creates a bookmark folder containing a bookmark for all open tabs. + virtual void BookmarkAllTabs() = 0; }; //////////////////////////////////////////////////////////////////////////////// @@ -464,6 +467,7 @@ class TabStripModel : public NotificationObserver { CommandCloseTabsOpenedBy, CommandRestoreTab, CommandTogglePinned, + CommandBookmarkAllTabs, CommandLast }; diff --git a/chrome/browser/tabs/tab_strip_model_unittest.cc b/chrome/browser/tabs/tab_strip_model_unittest.cc index 585fec5..5beb59f 100644 --- a/chrome/browser/tabs/tab_strip_model_unittest.cc +++ b/chrome/browser/tabs/tab_strip_model_unittest.cc @@ -65,6 +65,7 @@ class TabStripDummyDelegate : public TabStripModelDelegate { virtual bool CanRestoreTab() { return false; } virtual void RestoreTab() {} virtual bool CanCloseContentsAt(int index) { return can_close_ ; } + virtual void BookmarkAllTabs() {} private: // A dummy TabContents we give to callers that expect us to actually build a diff --git a/chrome/browser/views/bookmark_editor_view.cc b/chrome/browser/views/bookmark_editor_view.cc index bf47ec4..42d6447 100644 --- a/chrome/browser/views/bookmark_editor_view.cc +++ b/chrome/browser/views/bookmark_editor_view.cc @@ -87,11 +87,15 @@ BookmarkEditorView::~BookmarkEditorView() { bool BookmarkEditorView::IsDialogButtonEnabled( MessageBoxFlags::DialogButton button) const { if (button == MessageBoxFlags::DIALOGBUTTON_OK) { + if (IsEditingFolder()) + return !title_tf_.text().empty(); + const GURL url(GetInputURL()); return bb_model_->IsLoaded() && url.is_valid(); } return true; } + bool BookmarkEditorView::IsModal() const { return true; } @@ -263,7 +267,7 @@ void BookmarkEditorView::Init() { title_tf_.SetController(this); std::wstring url_text; - if (node_) { + if (node_ && !IsEditingFolder()) { std::wstring languages = profile_ ? profile_->GetPrefs()->GetString(prefs::kAcceptLanguages) : std::wstring(); @@ -271,7 +275,7 @@ void BookmarkEditorView::Init() { // false and unescape=false to show the original URL except IDN. url_text = net::FormatUrl(node_->GetURL(), languages, false, UnescapeRule::NONE, - NULL, NULL); + NULL, NULL); } url_tf_.SetText(url_text); url_tf_.SetController(this); @@ -323,12 +327,14 @@ void BookmarkEditorView::Init() { new Label(l10n_util::GetString(IDS_BOOMARK_EDITOR_NAME_LABEL))); layout->AddView(&title_tf_); - layout->AddPaddingRow(0, kRelatedControlVerticalSpacing); + if (!IsEditingFolder()) { + layout->AddPaddingRow(0, kRelatedControlVerticalSpacing); - layout->StartRow(0, labels_column_set_id); - layout->AddView( - new Label(l10n_util::GetString(IDS_BOOMARK_EDITOR_URL_LABEL))); - layout->AddView(&url_tf_); + layout->StartRow(0, labels_column_set_id); + layout->AddView( + new Label(l10n_util::GetString(IDS_BOOMARK_EDITOR_URL_LABEL))); + layout->AddView(&url_tf_); + } if (show_tree_) { layout->AddPaddingRow(0, kRelatedControlVerticalSpacing); @@ -441,12 +447,15 @@ BookmarkEditorView::EditorNode* BookmarkEditorView::AddNewGroup( return new_node; } +bool BookmarkEditorView::IsEditingFolder() const { + return node_ && node_->is_folder(); +} + void BookmarkEditorView::ExpandAndSelect() { tree_view_->ExpandAll(); const BookmarkNode* to_select = node_ ? node_->GetParent() : parent_; int64 group_id_to_select = to_select->id(); - DCHECK(group_id_to_select); // GetMostRecentParent should never return NULL. EditorNode* b_node = FindNodeWithID(tree_model_->GetRoot(), group_id_to_select); if (!b_node) @@ -469,9 +478,10 @@ void BookmarkEditorView::CreateNodes(const BookmarkNode* bb_node, BookmarkEditorView::EditorNode* b_node) { for (int i = 0; i < bb_node->GetChildCount(); ++i) { const BookmarkNode* child_bb_node = bb_node->GetChild(i); - if (child_bb_node->is_folder()) { + if (child_bb_node->is_folder() && + (!IsEditingFolder() || child_bb_node != node_)) { EditorNode* new_b_node = new EditorNode(child_bb_node->GetTitle(), - child_bb_node->id()); + child_bb_node->id()); b_node->Add(b_node->GetChildCount(), new_b_node); CreateNodes(child_bb_node, new_b_node); } diff --git a/chrome/browser/views/bookmark_editor_view.h b/chrome/browser/views/bookmark_editor_view.h index 0b1ae90..571c9ff 100644 --- a/chrome/browser/views/bookmark_editor_view.h +++ b/chrome/browser/views/bookmark_editor_view.h @@ -22,13 +22,16 @@ class NativeButton; class Window; } +class BookmarkEditorViewTest; class GURL; class Menu; class Profile; // View that allows the user to edit a bookmark/starred URL. The user can // change the URL, title and where the bookmark appears as well as adding -// new groups and changing the name of other groups. +// new groups and changing the name of other groups. The editor is used for +// both editing a url bookmark, as well as editing a folder bookmark when +// created from 'Bookmark all tabs'. // // Edits are applied to the BookmarkModel when the user presses 'OK'. // @@ -43,17 +46,27 @@ class BookmarkEditorView : public BookmarkEditor, public views::ContextMenuController, public views::SimpleMenuModel::Delegate, public BookmarkModelObserver { - FRIEND_TEST(BookmarkEditorViewTest, ChangeParent); - FRIEND_TEST(BookmarkEditorViewTest, ChangeParentAndURL); - FRIEND_TEST(BookmarkEditorViewTest, ChangeURLToExistingURL); - FRIEND_TEST(BookmarkEditorViewTest, EditTitleKeepsPosition); - FRIEND_TEST(BookmarkEditorViewTest, EditURLKeepsPosition); - FRIEND_TEST(BookmarkEditorViewTest, ModelsMatch); - FRIEND_TEST(BookmarkEditorViewTest, MoveToNewParent); - FRIEND_TEST(BookmarkEditorViewTest, NewURL); - FRIEND_TEST(BookmarkEditorViewTest, ChangeURLNoTree); - FRIEND_TEST(BookmarkEditorViewTest, ChangeTitleNoTree); public: + // Type of node in the tree. Public purely for testing. + typedef TreeNodeWithValue<int64> EditorNode; + + // Model for the TreeView. Trivial subclass that doesn't allow titles with + // empty strings. Public purely for testing. + class EditorTreeModel : public TreeNodeModel<EditorNode> { + public: + explicit EditorTreeModel(EditorNode* root) + : TreeNodeModel<EditorNode>(root) {} + + virtual void SetTitle(TreeModelNode* node, + const std::wstring& title) { + if (!title.empty()) + TreeNodeModel::SetTitle(node, title); + } + + private: + DISALLOW_COPY_AND_ASSIGN(EditorTreeModel); + }; + BookmarkEditorView(Profile* profile, const BookmarkNode* parent, const BookmarkNode* node, @@ -113,25 +126,7 @@ class BookmarkEditorView : public BookmarkEditor, bool is_mouse_gesture); private: - // Type of node in the tree. - typedef TreeNodeWithValue<int64> EditorNode; - - // Model for the TreeView. Trivial subclass that doesn't allow titles with - // empty strings. - class EditorTreeModel : public TreeNodeModel<EditorNode> { - public: - explicit EditorTreeModel(EditorNode* root) - : TreeNodeModel<EditorNode>(root) {} - - virtual void SetTitle(TreeModelNode* node, - const std::wstring& title) { - if (!title.empty()) - TreeNodeModel::SetTitle(node, title); - } - - private: - DISALLOW_COPY_AND_ASSIGN(EditorTreeModel); - }; + friend class BookmarkEditorViewTest; // Creates the necessary sub-views, configures them, adds them to the layout, // and requests the entries to display from the database. @@ -172,7 +167,7 @@ class BookmarkEditorView : public BookmarkEditor, EditorNode* CreateRootNode(); // Adds and creates a child node in b_node for all children of bb_node that - // are groups. + // are groups, except for |node_| if editing a folder. void CreateNodes(const BookmarkNode* bb_node, EditorNode* b_node); // Returns the node with the specified id, or NULL if one can't be found. @@ -220,6 +215,9 @@ class BookmarkEditorView : public BookmarkEditor, // internally by NewGroup and broken into a separate method for testing. EditorNode* AddNewGroup(EditorNode* parent); + // Returns true if editing a folder. + bool IsEditingFolder() const; + // Profile the entry is from. Profile* profile_; diff --git a/chrome/browser/views/bookmark_editor_view_unittest.cc b/chrome/browser/views/bookmark_editor_view_unittest.cc index 22570bb..789e1ee1 100644 --- a/chrome/browser/views/bookmark_editor_view_unittest.cc +++ b/chrome/browser/views/bookmark_editor_view_unittest.cc @@ -49,6 +49,40 @@ class BookmarkEditorViewTest : public testing::Test { return const_cast<BookmarkNode*>(GetNode(name)); } + BookmarkEditorView::EditorTreeModel* editor_tree_model() { + return editor_->tree_model_.get(); + } + + void CreateEditor(Profile* profile, + const BookmarkNode* parent, + const BookmarkNode* node, + BookmarkEditor::Configuration configuration, + BookmarkEditor::Handler* handler) { + editor_.reset(new BookmarkEditorView(profile, parent, node, configuration, + handler)); + } + + void SetTitleText(const std::wstring& title) { + editor_->title_tf_.SetText(title); + } + + void SetURLText(const std::wstring& text) { + editor_->url_tf_.SetText(text); + } + + void ApplyEdits(BookmarkEditorView::EditorNode* node) { + editor_->ApplyEdits(node); + } + + BookmarkEditorView::EditorNode* AddNewGroup( + BookmarkEditorView::EditorNode* parent) { + return editor_->AddNewGroup(parent); + } + + bool URLTFHasParent() { + return editor_->url_tf_.GetParent(); + } + private: // Creates the following structure: // bookmark bar node @@ -81,13 +115,15 @@ class BookmarkEditorViewTest : public testing::Test { model_->AddGroup(model_->other_node(), 1, L"OF1"); model_->AddURL(of1, 0, L"of1a", GURL(test_base + "of1a")); } + + scoped_ptr<BookmarkEditorView> editor_; }; // Makes sure the tree model matches that of the bookmark bar model. TEST_F(BookmarkEditorViewTest, ModelsMatch) { - BookmarkEditorView editor(profile_.get(), NULL, NULL, - BookmarkEditorView::SHOW_TREE, NULL); - BookmarkEditorView::EditorNode* editor_root = editor.tree_model_->GetRoot(); + CreateEditor(profile_.get(), NULL, NULL, BookmarkEditorView::SHOW_TREE, + NULL); + BookmarkEditorView::EditorNode* editor_root = editor_tree_model()->GetRoot(); // The root should have two children, one for the bookmark bar node, // the other for the 'other bookmarks' folder. ASSERT_EQ(2, editor_root->GetChildCount()); @@ -110,11 +146,11 @@ TEST_F(BookmarkEditorViewTest, ModelsMatch) { // Changes the title and makes sure parent/visual order doesn't change. TEST_F(BookmarkEditorViewTest, EditTitleKeepsPosition) { - BookmarkEditorView editor(profile_.get(), NULL, GetNode("a"), - BookmarkEditorView::SHOW_TREE, NULL); - editor.title_tf_.SetText(L"new_a"); + CreateEditor(profile_.get(), NULL, GetNode("a"), + BookmarkEditorView::SHOW_TREE, NULL); + SetTitleText(L"new_a"); - editor.ApplyEdits(editor.tree_model_->GetRoot()->GetChild(0)); + ApplyEdits(editor_tree_model()->GetRoot()->GetChild(0)); const BookmarkNode* bb_node = profile_->GetBookmarkModel()->GetBookmarkBarNode(); @@ -127,12 +163,12 @@ TEST_F(BookmarkEditorViewTest, EditTitleKeepsPosition) { TEST_F(BookmarkEditorViewTest, EditURLKeepsPosition) { Time node_time = Time::Now() + TimeDelta::FromDays(2); GetMutableNode("a")->set_date_added(node_time); - BookmarkEditorView editor(profile_.get(), NULL, GetNode("a"), - BookmarkEditorView::SHOW_TREE, NULL); + CreateEditor(profile_.get(), NULL, GetNode("a"), + BookmarkEditorView::SHOW_TREE, NULL); - editor.url_tf_.SetText(UTF8ToWide(GURL(base_path() + "new_a").spec())); + SetURLText(UTF8ToWide(GURL(base_path() + "new_a").spec())); - editor.ApplyEdits(editor.tree_model_->GetRoot()->GetChild(0)); + ApplyEdits(editor_tree_model()->GetRoot()->GetChild(0)); const BookmarkNode* bb_node = profile_->GetBookmarkModel()->GetBookmarkBarNode(); @@ -144,10 +180,10 @@ TEST_F(BookmarkEditorViewTest, EditURLKeepsPosition) { // Moves 'a' to be a child of the other node. TEST_F(BookmarkEditorViewTest, ChangeParent) { - BookmarkEditorView editor(profile_.get(), NULL, GetNode("a"), - BookmarkEditorView::SHOW_TREE, NULL); + CreateEditor(profile_.get(), NULL, GetNode("a"), + BookmarkEditorView::SHOW_TREE, NULL); - editor.ApplyEdits(editor.tree_model_->GetRoot()->GetChild(1)); + ApplyEdits(editor_tree_model()->GetRoot()->GetChild(1)); const BookmarkNode* other_node = profile_->GetBookmarkModel()->other_node(); ASSERT_EQ(L"a", other_node->GetChild(2)->GetTitle()); @@ -158,12 +194,12 @@ TEST_F(BookmarkEditorViewTest, ChangeParent) { TEST_F(BookmarkEditorViewTest, ChangeParentAndURL) { Time node_time = Time::Now() + TimeDelta::FromDays(2); GetMutableNode("a")->set_date_added(node_time); - BookmarkEditorView editor(profile_.get(), NULL, GetNode("a"), - BookmarkEditorView::SHOW_TREE, NULL); + CreateEditor(profile_.get(), NULL, GetNode("a"), + BookmarkEditorView::SHOW_TREE, NULL); - editor.url_tf_.SetText(UTF8ToWide(GURL(base_path() + "new_a").spec())); + SetURLText(UTF8ToWide(GURL(base_path() + "new_a").spec())); - editor.ApplyEdits(editor.tree_model_->GetRoot()->GetChild(1)); + ApplyEdits(editor_tree_model()->GetRoot()->GetChild(1)); const BookmarkNode* other_node = profile_->GetBookmarkModel()->other_node(); ASSERT_EQ(L"a", other_node->GetChild(2)->GetTitle()); @@ -173,19 +209,19 @@ TEST_F(BookmarkEditorViewTest, ChangeParentAndURL) { // Creates a new folder and moves a node to it. TEST_F(BookmarkEditorViewTest, MoveToNewParent) { - BookmarkEditorView editor(profile_.get(), NULL, GetNode("a"), - BookmarkEditorView::SHOW_TREE, NULL); + CreateEditor(profile_.get(), NULL, GetNode("a"), + BookmarkEditorView::SHOW_TREE, NULL); // Create two nodes: "F21" as a child of "F2" and "F211" as a child of "F21". BookmarkEditorView::EditorNode* f2 = - editor.tree_model_->GetRoot()->GetChild(0)->GetChild(1); - BookmarkEditorView::EditorNode* f21 = editor.AddNewGroup(f2); + editor_tree_model()->GetRoot()->GetChild(0)->GetChild(1); + BookmarkEditorView::EditorNode* f21 = AddNewGroup(f2); f21->SetTitle(L"F21"); - BookmarkEditorView::EditorNode* f211 = editor.AddNewGroup(f21); + BookmarkEditorView::EditorNode* f211 = AddNewGroup(f21); f211->SetTitle(L"F211"); // Parent the node to "F21". - editor.ApplyEdits(f2); + ApplyEdits(f2); const BookmarkNode* bb_node = profile_->GetBookmarkModel()->GetBookmarkBarNode(); @@ -206,13 +242,13 @@ TEST_F(BookmarkEditorViewTest, MoveToNewParent) { // Brings up the editor, creating a new URL on the bookmark bar. TEST_F(BookmarkEditorViewTest, NewURL) { - BookmarkEditorView editor(profile_.get(), NULL, NULL, - BookmarkEditorView::SHOW_TREE, NULL); + CreateEditor(profile_.get(), NULL, NULL, BookmarkEditorView::SHOW_TREE, + NULL); - editor.url_tf_.SetText(UTF8ToWide(GURL(base_path() + "a").spec())); - editor.title_tf_.SetText(L"new_a"); + SetURLText(UTF8ToWide(GURL(base_path() + "a").spec())); + SetTitleText(L"new_a"); - editor.ApplyEdits(editor.tree_model_->GetRoot()->GetChild(0)); + ApplyEdits(editor_tree_model()->GetRoot()->GetChild(0)); const BookmarkNode* bb_node = profile_->GetBookmarkModel()->GetBookmarkBarNode(); @@ -226,14 +262,13 @@ TEST_F(BookmarkEditorViewTest, NewURL) { // Brings up the editor with no tree and modifies the url. TEST_F(BookmarkEditorViewTest, ChangeURLNoTree) { - BookmarkEditorView editor(profile_.get(), NULL, - model_->other_node()->GetChild(0), - BookmarkEditorView::NO_TREE, NULL); + CreateEditor(profile_.get(), NULL, model_->other_node()->GetChild(0), + BookmarkEditorView::NO_TREE, NULL); - editor.url_tf_.SetText(UTF8ToWide(GURL(base_path() + "a").spec())); - editor.title_tf_.SetText(L"new_a"); + SetURLText(UTF8ToWide(GURL(base_path() + "a").spec())); + SetTitleText(L"new_a"); - editor.ApplyEdits(NULL); + ApplyEdits(NULL); const BookmarkNode* other_node = profile_->GetBookmarkModel()->other_node(); ASSERT_EQ(2, other_node->GetChildCount()); @@ -246,13 +281,12 @@ TEST_F(BookmarkEditorViewTest, ChangeURLNoTree) { // Brings up the editor with no tree and modifies only the title. TEST_F(BookmarkEditorViewTest, ChangeTitleNoTree) { - BookmarkEditorView editor(profile_.get(), NULL, - model_->other_node()->GetChild(0), - BookmarkEditorView::NO_TREE, NULL); + CreateEditor(profile_.get(), NULL, model_->other_node()->GetChild(0), + BookmarkEditorView::NO_TREE, NULL); - editor.title_tf_.SetText(L"new_a"); + SetTitleText(L"new_a"); - editor.ApplyEdits(NULL); + ApplyEdits(NULL); const BookmarkNode* other_node = profile_->GetBookmarkModel()->other_node(); ASSERT_EQ(2, other_node->GetChildCount()); @@ -261,3 +295,63 @@ TEST_F(BookmarkEditorViewTest, ChangeTitleNoTree) { EXPECT_EQ(L"new_a", new_node->GetTitle()); } + +// Modifies the title of a folder. +TEST_F(BookmarkEditorViewTest, ModifyFolderTitle) { + int64 start_id = model_->GetBookmarkBarNode()->GetChild(2)->id(); + CreateEditor(profile_.get(), NULL, model_->GetBookmarkBarNode()->GetChild(2), + BookmarkEditorView::SHOW_TREE, NULL); + + // The url field shouldn't be visible. + EXPECT_FALSE(URLTFHasParent()); + SetTitleText(L"new_F"); + + // Make sure the tree isn't showing the folder we're editing. + EXPECT_EQ(1, editor_tree_model()->GetRoot()->GetChild(0)->GetChildCount()); + + ApplyEdits(editor_tree_model()->GetRoot()->GetChild(0)); + + // Make sure the folder we edited is still there. + ASSERT_EQ(3, model_->GetBookmarkBarNode()->GetChildCount()); + EXPECT_EQ(start_id, model_->GetBookmarkBarNode()->GetChild(2)->id()); + EXPECT_TRUE(model_->GetBookmarkBarNode()->GetChild(2)->is_folder()); + EXPECT_EQ(L"new_F", model_->GetBookmarkBarNode()->GetChild(2)->GetTitle()); +} + +// Moves a folder. +TEST_F(BookmarkEditorViewTest, MoveFolder) { + const BookmarkNode* node = model_->GetBookmarkBarNode()->GetChild(2); + int64 start_id = node->id(); + CreateEditor(profile_.get(), NULL, node, BookmarkEditorView::SHOW_TREE, NULL); + + SetTitleText(L"new_F"); + + // Moves to the 'other' folder. + ApplyEdits(editor_tree_model()->GetRoot()->GetChild(1)); + + // Make sure the folder we edited is still there. + ASSERT_EQ(3, model_->other_node()->GetChildCount()); + EXPECT_EQ(node, model_->other_node()->GetChild(2)); + EXPECT_TRUE(node->is_folder()); + EXPECT_EQ(L"new_F", node->GetTitle()); +} + +// Moves a folder under a new folder. +TEST_F(BookmarkEditorViewTest, MoveFolderNewParent) { + const BookmarkNode* node = model_->GetBookmarkBarNode()->GetChild(2); + CreateEditor(profile_.get(), NULL, node, BookmarkEditorView::SHOW_TREE, NULL); + + BookmarkEditorView::EditorNode* other = + editor_tree_model()->GetRoot()->GetChild(1); + BookmarkEditorView::EditorNode* new_f = AddNewGroup(other); + new_f->SetTitle(L"new_f"); + + ApplyEdits(new_f); + + // Make sure the folder we edited is still there. + ASSERT_EQ(3, model_->other_node()->GetChildCount()); + const BookmarkNode* new_folder = model_->other_node()->GetChild(2); + EXPECT_EQ(L"new_f", new_folder->GetTitle()); + ASSERT_EQ(1, new_folder->GetChildCount()); + ASSERT_EQ(node, new_folder->GetChild(0)); +} diff --git a/chrome/browser/views/tabs/tab.cc b/chrome/browser/views/tabs/tab.cc index 93d5cb2..9ff31b0 100644 --- a/chrome/browser/views/tabs/tab.cc +++ b/chrome/browser/views/tabs/tab.cc @@ -85,6 +85,8 @@ class Tab::TabContextMenuContents : public views::SimpleMenuModel, AddItemWithStringId(TabStripModel::CommandReload, IDS_TAB_CXMENU_RELOAD); AddItemWithStringId(TabStripModel::CommandDuplicate, IDS_TAB_CXMENU_DUPLICATE); + AddCheckItemWithStringId(TabStripModel::CommandTogglePinned, + IDS_TAB_CXMENU_PIN_TAB); AddSeparator(); AddItemWithStringId(TabStripModel::CommandCloseTab, IDS_TAB_CXMENU_CLOSETAB); @@ -94,10 +96,12 @@ class Tab::TabContextMenuContents : public views::SimpleMenuModel, IDS_TAB_CXMENU_CLOSETABSTORIGHT); AddItemWithStringId(TabStripModel::CommandCloseTabsOpenedBy, IDS_TAB_CXMENU_CLOSETABSOPENEDBY); - AddItemWithStringId(TabStripModel::CommandRestoreTab, IDS_RESTORE_TAB); AddSeparator(); - AddCheckItemWithStringId(TabStripModel::CommandTogglePinned, - IDS_TAB_CXMENU_PIN_TAB); + AddItemWithStringId(TabStripModel::CommandRestoreTab, IDS_RESTORE_TAB); +#if defined(OS_WIN) + AddItemWithStringId(TabStripModel::CommandBookmarkAllTabs, + IDS_TAB_CXMENU_BOOKMARK_ALL_TABS); +#endif menu_.reset(new views::Menu2(this)); } |