diff options
author | sky@google.com <sky@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-10-29 23:38:06 +0000 |
---|---|---|
committer | sky@google.com <sky@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-10-29 23:38:06 +0000 |
commit | 7f856bee73ffdccdbbbbbab4cb79185290d38359 (patch) | |
tree | a837328e08a113abdc70b2fc0ae2f2a4a3f804eb /chrome/browser/bookmarks | |
parent | 281fe14063dd8fb81cea102f5abb7b82f407c3d1 (diff) | |
download | chromium_src-7f856bee73ffdccdbbbbbab4cb79185290d38359.zip chromium_src-7f856bee73ffdccdbbbbbab4cb79185290d38359.tar.gz chromium_src-7f856bee73ffdccdbbbbbab4cb79185290d38359.tar.bz2 |
First cut at the bookmark manager. There are still a fair number of
rough edges, but I'm at a good point where I want to land what I
have. Here's what is left:
. Flicker on show, likely the result of restoring window placement.
. tree flickers when dragging splitter.
. table/tree need to autoscroll when drop cursor held at bottom of view.
. prompts for deleting.
. When you move an item the table snaps to the top, this is because
I'm sending out model changed. need a better notification.
. Operations in menu to add need to change selection.
. Remember split location.
I would have preferred to split this up into a couple of reviews, but
everything is intertwined now. Sorry.
BUG=674
TEST=don't test the bookmark manager yet, but make sure bookmark bar
still works.
Review URL: http://codereview.chromium.org/8197
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@4191 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/bookmarks')
-rw-r--r-- | chrome/browser/bookmarks/bookmark_context_menu.cc | 458 | ||||
-rw-r--r-- | chrome/browser/bookmarks/bookmark_context_menu.h | 105 | ||||
-rw-r--r-- | chrome/browser/bookmarks/bookmark_context_menu_test.cc | 271 | ||||
-rw-r--r-- | chrome/browser/bookmarks/bookmark_drag_utils.cc | 91 | ||||
-rw-r--r-- | chrome/browser/bookmarks/bookmark_folder_tree_model.cc | 2 | ||||
-rw-r--r-- | chrome/browser/bookmarks/bookmark_utils.cc | 241 | ||||
-rw-r--r-- | chrome/browser/bookmarks/bookmark_utils.h (renamed from chrome/browser/bookmarks/bookmark_drag_utils.h) | 36 |
7 files changed, 1106 insertions, 98 deletions
diff --git a/chrome/browser/bookmarks/bookmark_context_menu.cc b/chrome/browser/bookmarks/bookmark_context_menu.cc new file mode 100644 index 0000000..4f033ac --- /dev/null +++ b/chrome/browser/bookmarks/bookmark_context_menu.cc @@ -0,0 +1,458 @@ +// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/bookmarks/bookmark_context_menu.h" + +#include "chrome/browser/bookmarks/bookmark_model.h" +#include "chrome/browser/bookmarks/bookmark_utils.h" +#include "chrome/browser/browser.h" +#include "chrome/browser/browser_list.h" +#include "chrome/browser/page_navigator.h" +#include "chrome/browser/profile.h" +#include "chrome/browser/tab_contents.h" +#include "chrome/browser/user_metrics.h" +#include "chrome/browser/views/bookmark_bar_view.h" +#include "chrome/browser/views/bookmark_editor_view.h" +#include "chrome/browser/views/bookmark_manager_view.h" +#include "chrome/browser/views/input_window.h" +#include "chrome/common/l10n_util.h" +#include "chrome/common/pref_names.h" +#include "chrome/common/pref_service.h" +#include "chrome/views/container.h" +#include "chrome/views/window.h" + +#include "generated_resources.h" + +namespace { + +// Returns true if the specified node is of type URL, or has a descendant +// of type URL. +bool NodeHasURLs(BookmarkNode* node) { + if (node->is_url()) + return true; + + for (int i = 0; i < node->GetChildCount(); ++i) { + if (NodeHasURLs(node->GetChild(i))) + return true; + } + return false; +} + +// EditFolderController ------------------------------------------------------- + +// EditFolderController manages the editing and/or creation of a folder. If the +// user presses ok, the name change is committed to the model. +// +// EditFolderController deletes itself when the window is closed. +class EditFolderController : public InputWindowDelegate, + public BookmarkModelObserver { + public: + virtual ~EditFolderController() { + if (model_) + model_->RemoveObserver(this); + } + + static void Show(Profile* profile, + HWND hwnd, + BookmarkNode* node, + bool is_new) { + // EditFolderController deletes itself when done. + EditFolderController* controller = + new EditFolderController(profile, hwnd, node, is_new); + controller->Show(); + } + + private: + EditFolderController(Profile* profile, + HWND hwnd, + BookmarkNode* node, + bool is_new) + : profile_(profile), + model_(profile->GetBookmarkModel()), + node_(node), + is_new_(is_new) { + DCHECK(is_new_ || node); + window_ = CreateInputWindow(hwnd, this); + model_->AddObserver(this); + } + + void Show() { + window_->Show(); + } + + // InputWindowDelegate methods. + virtual std::wstring GetTextFieldLabel() { + return l10n_util::GetString(IDS_BOOMARK_BAR_EDIT_FOLDER_LABEL); + } + + virtual std::wstring GetTextFieldContents() { + if (is_new_) + return l10n_util::GetString(IDS_BOOMARK_EDITOR_NEW_FOLDER_NAME); + return node_->GetTitle(); + } + + virtual bool IsValid(const std::wstring& text) { + return !text.empty(); + } + + virtual void InputAccepted(const std::wstring& text) { + if (is_new_) + model_->AddGroup(node_, node_->GetChildCount(), text); + else + model_->SetTitle(node_, text); + } + + virtual void InputCanceled() { + } + + virtual void WindowClosing() { + delete this; + } + + virtual std::wstring GetWindowTitle() const { + return is_new_ ? + l10n_util::GetString(IDS_BOOMARK_FOLDER_EDITOR_WINDOW_TITLE_NEW) : + l10n_util::GetString(IDS_BOOMARK_FOLDER_EDITOR_WINDOW_TITLE); + } + + // BookmarkModelObserver methods, all invoke ModelChanged and close the + // dialog. + virtual void Loaded(BookmarkModel* model) {} + virtual void BookmarkModelBeingDeleted(BookmarkModel* model) { + model_->RemoveObserver(this); + model_ = NULL; + ModelChanged(); + } + + virtual void BookmarkNodeMoved(BookmarkModel* model, + BookmarkNode* old_parent, + int old_index, + BookmarkNode* new_parent, + int new_index) { + ModelChanged(); + } + + virtual void BookmarkNodeAdded(BookmarkModel* model, + BookmarkNode* parent, + int index) { + ModelChanged(); + } + + virtual void BookmarkNodeRemoved(BookmarkModel* model, + BookmarkNode* parent, + int index, + BookmarkNode* node) { + ModelChanged(); + } + + virtual void BookmarkNodeChanged(BookmarkModel* model, BookmarkNode* node) { + ModelChanged(); + } + + virtual void BookmarkNodeFavIconLoaded(BookmarkModel* model, + BookmarkNode* node) {} + + void ModelChanged() { + window_->Close(); + } + + Profile* profile_; + BookmarkModel* model_; + // If is_new is true, this is the parent to create the new node under. + // Otherwise this is the node to change the title of. + BookmarkNode* node_; + + bool is_new_; + views::Window* window_; + + DISALLOW_COPY_AND_ASSIGN(EditFolderController); +}; + +} // namespace + +// BookmarkContextMenu ------------------------------------------- + +BookmarkContextMenu::BookmarkContextMenu( + HWND hwnd, + Profile* profile, + Browser* browser, + PageNavigator* navigator, + BookmarkNode* parent, + const std::vector<BookmarkNode*>& selection, + ConfigurationType configuration) + : hwnd_(hwnd), + profile_(profile), + browser_(browser), + navigator_(navigator), + parent_(parent), + selection_(selection), + model_(profile->GetBookmarkModel()), + configuration_(configuration) { + DCHECK(profile_); + DCHECK(model_->IsLoaded()); + menu_.reset(new views::MenuItemView(this)); + if (selection.size() == 1 && selection[0]->is_url()) { + menu_->AppendMenuItemWithLabel( + IDS_BOOMARK_BAR_OPEN_ALL, + l10n_util::GetString(IDS_BOOMARK_BAR_OPEN_IN_NEW_TAB)); + menu_->AppendMenuItemWithLabel( + IDS_BOOMARK_BAR_OPEN_ALL_NEW_WINDOW, + l10n_util::GetString(IDS_BOOMARK_BAR_OPEN_IN_NEW_WINDOW)); + menu_->AppendMenuItemWithLabel( + IDS_BOOMARK_BAR_OPEN_ALL_INCOGNITO, + l10n_util::GetString(IDS_BOOMARK_BAR_OPEN_INCOGNITO)); + } else { + menu_->AppendMenuItemWithLabel( + IDS_BOOMARK_BAR_OPEN_ALL, + l10n_util::GetString(IDS_BOOMARK_BAR_OPEN_ALL)); + menu_->AppendMenuItemWithLabel( + IDS_BOOMARK_BAR_OPEN_ALL_NEW_WINDOW, + l10n_util::GetString(IDS_BOOMARK_BAR_OPEN_ALL_NEW_WINDOW)); + menu_->AppendMenuItemWithLabel( + IDS_BOOMARK_BAR_OPEN_ALL_INCOGNITO, + l10n_util::GetString(IDS_BOOMARK_BAR_OPEN_ALL_INCOGNITO)); + } + menu_->AppendSeparator(); + + menu_->AppendMenuItemWithLabel(IDS_BOOKMARK_BAR_EDIT, + l10n_util::GetString(IDS_BOOKMARK_BAR_EDIT)); + menu_->AppendMenuItemWithLabel( + IDS_BOOKMARK_BAR_REMOVE, + l10n_util::GetString(IDS_BOOKMARK_BAR_REMOVE)); + + if (configuration != BOOKMARK_BAR) { + menu_->AppendMenuItemWithLabel( + IDS_BOOKMARK_MANAGER_SHOW_IN_FOLDER, + l10n_util::GetString(IDS_BOOKMARK_MANAGER_SHOW_IN_FOLDER)); + } + + menu_->AppendSeparator(); + + menu_->AppendMenuItemWithLabel( + IDS_BOOMARK_BAR_ADD_NEW_BOOKMARK, + l10n_util::GetString(IDS_BOOMARK_BAR_ADD_NEW_BOOKMARK)); + menu_->AppendMenuItemWithLabel( + IDS_BOOMARK_BAR_NEW_FOLDER, + l10n_util::GetString(IDS_BOOMARK_BAR_NEW_FOLDER)); + + if (configuration == BOOKMARK_BAR) { + menu_->AppendSeparator(); + menu_->AppendMenuItemWithLabel(IDS_BOOKMARK_MANAGER, + l10n_util::GetString(IDS_BOOKMARK_MANAGER)); + menu_->AppendMenuItem(IDS_BOOMARK_BAR_ALWAYS_SHOW, + l10n_util::GetString(IDS_BOOMARK_BAR_ALWAYS_SHOW), + views::MenuItemView::CHECKBOX); + } + model_->AddObserver(this); +} + +BookmarkContextMenu::~BookmarkContextMenu() { + if (model_) + model_->RemoveObserver(this); +} + +void BookmarkContextMenu::RunMenuAt(int x, int y) { + if (!model_->IsLoaded()) { + NOTREACHED(); + return; + } + // width/height don't matter here. + menu_->RunMenuAt(hwnd_, gfx::Rect(x, y, 0, 0), views::MenuItemView::TOPLEFT, + true); +} + +void BookmarkContextMenu::ExecuteCommand(int id) { + switch (id) { + case IDS_BOOMARK_BAR_OPEN_ALL: + case IDS_BOOMARK_BAR_OPEN_ALL_INCOGNITO: + case IDS_BOOMARK_BAR_OPEN_ALL_NEW_WINDOW: { + PageNavigator* navigator = browser_ ? + browser_->GetSelectedTabContents() : navigator_; + WindowOpenDisposition initial_disposition; + if (id == IDS_BOOMARK_BAR_OPEN_ALL) { + initial_disposition = NEW_FOREGROUND_TAB; + UserMetrics::RecordAction(L"BookmarkBar_ContextMenu_OpenAll", + profile_); + } else if (id == IDS_BOOMARK_BAR_OPEN_ALL_NEW_WINDOW) { + initial_disposition = NEW_WINDOW; + UserMetrics::RecordAction( + L"BookmarkBar_ContextMenu_OpenAllInNewWindow", profile_); + } else { + initial_disposition = OFF_THE_RECORD; + UserMetrics::RecordAction( + L"BookmarkBar_ContextMenu_OpenAllIncognito", profile_); + } + + bookmark_utils::OpenAll(hwnd_, profile_, navigator, selection_, + initial_disposition); + break; + } + + case IDS_BOOKMARK_BAR_EDIT: + UserMetrics::RecordAction(L"BookmarkBar_ContextMenu_Edit", profile_); + + if (selection_.size() != 1) { + NOTREACHED(); + return; + } + + if (selection_[0]->is_url()) { + BookmarkEditorView::Configuration editor_config; + if (configuration_ == BOOKMARK_BAR) + editor_config = BookmarkEditorView::SHOW_TREE; + else + editor_config = BookmarkEditorView::NO_TREE; + BookmarkEditorView::Show(hwnd_, profile_, NULL, selection_[0], + editor_config); + } else { + EditFolderController::Show(profile_, hwnd_, selection_[0], false); + } + break; + + case IDS_BOOKMARK_BAR_REMOVE: { + UserMetrics::RecordAction(L"BookmarkBar_ContextMenu_Remove", profile_); + BookmarkModel* model = RemoveModelObserver(); + + for (size_t i = 0; i < selection_.size(); ++i) { + model->Remove(selection_[i]->GetParent(), + selection_[i]->GetParent()->IndexOfChild(selection_[i])); + } + selection_.clear(); + break; + } + + case IDS_BOOMARK_BAR_ADD_NEW_BOOKMARK: { + UserMetrics::RecordAction(L"BookmarkBar_ContextMenu_Add", profile_); + + BookmarkEditorView::Configuration editor_config; + if (configuration_ == BOOKMARK_BAR) + editor_config = BookmarkEditorView::SHOW_TREE; + else + editor_config = BookmarkEditorView::NO_TREE; + BookmarkEditorView::Show(hwnd_, profile_, GetParentForNewNodes(), NULL, + editor_config); + break; + } + + case IDS_BOOMARK_BAR_NEW_FOLDER: { + UserMetrics::RecordAction(L"BookmarkBar_ContextMenu_NewFolder", + profile_); + + EditFolderController::Show(profile_, hwnd_, GetParentForNewNodes(), + true); + break; + } + + case IDS_BOOMARK_BAR_ALWAYS_SHOW: + BookmarkBarView::ToggleWhenVisible(profile_); + break; + + case IDS_BOOKMARK_MANAGER_SHOW_IN_FOLDER: + UserMetrics::RecordAction(L"BookmarkBar_ContextMenu_ShowInFolder", + profile_); + + if (selection_.size() != 1) { + NOTREACHED(); + return; + } + + if (BookmarkManagerView::current()) + BookmarkManagerView::current()->SelectInTree(selection_[0]); + break; + + default: + NOTREACHED(); + } +} + +bool BookmarkContextMenu::IsItemChecked(int id) const { + DCHECK(id == IDS_BOOMARK_BAR_ALWAYS_SHOW); + return profile_->GetPrefs()->GetBoolean(prefs::kShowBookmarkBar); +} + +bool BookmarkContextMenu::IsCommandEnabled(int id) const { + bool is_root_node = + (selection_.size() == 1 && + selection_[0]->GetParent() == model_->root_node()); + switch (id) { + case IDS_BOOMARK_BAR_OPEN_INCOGNITO: + return !profile_->IsOffTheRecord(); + + case IDS_BOOMARK_BAR_OPEN_ALL_INCOGNITO: + return HasURLs() && !profile_->IsOffTheRecord(); + + case IDS_BOOMARK_BAR_OPEN_ALL: + case IDS_BOOMARK_BAR_OPEN_ALL_NEW_WINDOW: + return HasURLs(); + + case IDS_BOOKMARK_BAR_EDIT: + return selection_.size() == 1 && !is_root_node; + + case IDS_BOOKMARK_BAR_REMOVE: + return !selection_.empty() && !is_root_node; + + case IDS_BOOKMARK_MANAGER_SHOW_IN_FOLDER: + return configuration_ == BOOKMARK_MANAGER_TABLE && + selection_.size() == 1; + + case IDS_BOOMARK_BAR_NEW_FOLDER: + case IDS_BOOMARK_BAR_ADD_NEW_BOOKMARK: + return GetParentForNewNodes() != NULL; + } + return true; +} + +void BookmarkContextMenu::BookmarkModelBeingDeleted(BookmarkModel* model) { + ModelChanged(); +} + +void BookmarkContextMenu::BookmarkNodeMoved(BookmarkModel* model, + BookmarkNode* old_parent, + int old_index, + BookmarkNode* new_parent, + int new_index) { + ModelChanged(); +} + +void BookmarkContextMenu::BookmarkNodeAdded(BookmarkModel* model, + BookmarkNode* parent, + int index) { + ModelChanged(); +} + +void BookmarkContextMenu::BookmarkNodeRemoved(BookmarkModel* model, + BookmarkNode* parent, + int index, + BookmarkNode* node) { + ModelChanged(); +} + +void BookmarkContextMenu::BookmarkNodeChanged(BookmarkModel* model, + BookmarkNode* node) { + ModelChanged(); +} + +void BookmarkContextMenu::ModelChanged() { + menu_->Cancel(); +} + +BookmarkModel* BookmarkContextMenu::RemoveModelObserver() { + BookmarkModel* model = model_; + model_->RemoveObserver(this); + model_ = NULL; + return model; +} + +bool BookmarkContextMenu::HasURLs() const { + for (size_t i = 0; i < selection_.size(); ++i) { + if (NodeHasURLs(selection_[i])) + return true; + } + return false; +} + +BookmarkNode* BookmarkContextMenu::GetParentForNewNodes() const { + return (selection_.size() == 1 && selection_[0]->is_folder()) ? + selection_[0] : parent_; +} diff --git a/chrome/browser/bookmarks/bookmark_context_menu.h b/chrome/browser/bookmarks/bookmark_context_menu.h new file mode 100644 index 0000000..5b48627 --- /dev/null +++ b/chrome/browser/bookmarks/bookmark_context_menu.h @@ -0,0 +1,105 @@ +// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_BOOKMARKS_BOOKMARK_CONTEXT_MENU_H_ +#define CHROME_BROWSER_BOOKMARKS_BOOKMARK_CONTEXT_MENU_H_ + +#include <vector> + +#include "chrome/browser/bookmarks/bookmark_model.h" +#include "chrome/views/chrome_menu.h" + +class Browser; +class PageNavigator; + +// BookmarkContextMenu manages the context menu shown for the +// bookmark bar, items on the bookmark bar, submenus of the bookmark bar and +// the bookmark manager. +class BookmarkContextMenu : public views::MenuDelegate, + public BookmarkModelObserver { + public: + // Used to configure what the context menu shows. + enum ConfigurationType { + BOOKMARK_BAR, + BOOKMARK_MANAGER_TABLE, + BOOKMARK_MANAGER_TREE + }; + + // Creates the bookmark context menu. + // |profile| is used for opening urls as well as enabling 'open incognito'. + // |browser| is used to determine the PageNavigator and may be null. + // |navigator| is used if |browser| is null, and is provided for testing. + // |parent| is the parent for newly created nodes if |selection| is empty. + // |selection| is the nodes the context menu operates on and may be empty. + // |configuration| determines which items to show. + BookmarkContextMenu(HWND hwnd, + Profile* profile, + Browser* browser, + PageNavigator* navigator, + BookmarkNode* parent, + const std::vector<BookmarkNode*>& selection, + ConfigurationType configuration); + virtual ~BookmarkContextMenu(); + + // Shows the menu at the specified place. + void RunMenuAt(int x, int y); + + // Returns the menu. + views::MenuItemView* menu() const { return menu_.get(); } + + // Menu::Delegate methods. + virtual void ExecuteCommand(int id); + virtual bool IsItemChecked(int id) const; + virtual bool IsCommandEnabled(int id) const; + + private: + // BookmarkModelObserver method. Any change to the model results in closing + // the menu. + virtual void Loaded(BookmarkModel* model) {} + virtual void BookmarkModelBeingDeleted(BookmarkModel* model); + virtual void BookmarkNodeMoved(BookmarkModel* model, + BookmarkNode* old_parent, + int old_index, + BookmarkNode* new_parent, + int new_index); + virtual void BookmarkNodeAdded(BookmarkModel* model, + BookmarkNode* parent, + int index); + virtual void BookmarkNodeRemoved(BookmarkModel* model, + BookmarkNode* parent, + int index, + BookmarkNode* node); + virtual void BookmarkNodeChanged(BookmarkModel* model, + BookmarkNode* node); + virtual void BookmarkNodeFavIconLoaded(BookmarkModel* model, + BookmarkNode* node) {} + + // Invoked from the various bookmark model observer methods. Closes the menu. + void ModelChanged(); + + // Removes the observer from the model and NULLs out model_. + BookmarkModel* RemoveModelObserver(); + + // Returns true if selection_ has at least one bookmark of type url. + bool HasURLs() const; + + // Returns the parent for newly created folders/bookmarks. If selection_ + // has one element and it is a folder, selection_[0] is returned, otherwise + // parent_ is returned. + BookmarkNode* GetParentForNewNodes() const; + + HWND hwnd_; + Profile* profile_; + Browser* browser_; + PageNavigator* navigator_; + BookmarkNode* parent_; + std::vector<BookmarkNode*> selection_; + scoped_ptr<views::MenuItemView> menu_; + BookmarkModel* model_; + ConfigurationType configuration_; + + DISALLOW_COPY_AND_ASSIGN(BookmarkContextMenu); +}; + +#endif // CHROME_BROWSER_BOOKMARKS_BOOKMARK_CONTEXT_MENU_H_ diff --git a/chrome/browser/bookmarks/bookmark_context_menu_test.cc b/chrome/browser/bookmarks/bookmark_context_menu_test.cc new file mode 100644 index 0000000..e665058 --- /dev/null +++ b/chrome/browser/bookmarks/bookmark_context_menu_test.cc @@ -0,0 +1,271 @@ +// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/bookmarks/bookmark_context_menu.h" +#include "chrome/browser/bookmarks/bookmark_model.h" +#include "chrome/browser/bookmarks/bookmark_utils.h" +#include "chrome/browser/profile.h" +#include "chrome/browser/views/bookmark_bar_view.h" +#include "chrome/common/pref_names.h" +#include "chrome/common/pref_service.h" +#include "chrome/browser/page_navigator.h" +#include "chrome/test/testing_profile.h" +#include "testing/gtest/include/gtest/gtest.h" + +#include "generated_resources.h" + +namespace { + +// PageNavigator implementation that records the URL. +class TestingPageNavigator : public PageNavigator { + public: + virtual void OpenURL(const GURL& url, + const GURL& referrer, + WindowOpenDisposition disposition, + PageTransition::Type transition) { + urls_.push_back(url); + } + + std::vector<GURL> urls_; +}; + +} // namespace + +class BookmarkContextMenuTest : public testing::Test { + public: + BookmarkContextMenuTest() + : model_(NULL) { + } + + virtual void SetUp() { + BookmarkBarView::testing_ = true; + + profile_.reset(new TestingProfile()); + profile_->set_has_history_service(true); + profile_->CreateBookmarkModel(true); + profile_->BlockUntilBookmarkModelLoaded(); + + model_ = profile_->GetBookmarkModel(); + + AddTestData(); + } + + virtual void TearDown() { + BookmarkBarView::testing_ = false; + + // Flush the message loop to make Purify happy. + message_loop_.RunAllPending(); + } + + protected: + MessageLoopForUI message_loop_; + scoped_ptr<TestingProfile> profile_; + BookmarkModel* model_; + TestingPageNavigator navigator_; + + private: + // Creates the following structure: + // a + // F1 + // f1a + // F11 + // f11a + // F2 + // F3 + // F4 + // f4a + void AddTestData() { + std::string test_base = "file:///c:/tmp/"; + + model_->AddURL(model_->GetBookmarkBarNode(), 0, L"a", + GURL(test_base + "a")); + BookmarkNode* f1 = + model_->AddGroup(model_->GetBookmarkBarNode(), 1, L"F1"); + model_->AddURL(f1, 0, L"f1a", GURL(test_base + "f1a")); + BookmarkNode* f11 = model_->AddGroup(f1, 1, L"F11"); + model_->AddURL(f11, 0, L"f11a", GURL(test_base + "f11a")); + model_->AddGroup(model_->GetBookmarkBarNode(), 2, L"F2"); + model_->AddGroup(model_->GetBookmarkBarNode(), 3, L"F3"); + BookmarkNode* f4 = + model_->AddGroup(model_->GetBookmarkBarNode(), 4, L"F4"); + model_->AddURL(f4, 0, L"f4a", GURL(test_base + "f4a")); + } +}; + +// Tests Deleting from the menu. +TEST_F(BookmarkContextMenuTest, DeleteURL) { + std::vector<BookmarkNode*> nodes; + nodes.push_back(model_->GetBookmarkBarNode()->GetChild(0)); + BookmarkContextMenu controller( + NULL, profile_.get(), NULL, NULL, nodes[0]->GetParent(), nodes, + BookmarkContextMenu::BOOKMARK_BAR); + GURL url = model_->GetBookmarkBarNode()->GetChild(0)->GetURL(); + ASSERT_TRUE(controller.IsCommandEnabled(IDS_BOOKMARK_BAR_REMOVE)); + // Delete the URL. + controller.ExecuteCommand(IDS_BOOKMARK_BAR_REMOVE); + // Model shouldn't have URL anymore. + ASSERT_FALSE(model_->IsBookmarked(url)); +} + +// Tests open all on a folder with a couple of bookmarks. +TEST_F(BookmarkContextMenuTest, OpenAll) { + BookmarkNode* folder = model_->GetBookmarkBarNode()->GetChild(1); + bookmark_utils::OpenAll( + NULL, profile_.get(), &navigator_, folder, NEW_FOREGROUND_TAB); + + // Should have navigated to F1's children. + ASSERT_EQ(2, navigator_.urls_.size()); + ASSERT_TRUE(folder->GetChild(0)->GetURL() == navigator_.urls_[0]); + ASSERT_TRUE(folder->GetChild(1)->GetChild(0)->GetURL() == + navigator_.urls_[1]); +} + +// Tests the enabled state of the menus when supplied an empty vector. +TEST_F(BookmarkContextMenuTest, EmptyNodes) { + BookmarkContextMenu controller( + NULL, profile_.get(), NULL, NULL, model_->other_node(), + std::vector<BookmarkNode*>(), BookmarkContextMenu::BOOKMARK_BAR); + EXPECT_FALSE(controller.IsCommandEnabled(IDS_BOOMARK_BAR_OPEN_ALL)); + EXPECT_FALSE( + controller.IsCommandEnabled(IDS_BOOMARK_BAR_OPEN_ALL_NEW_WINDOW)); + EXPECT_FALSE(controller.IsCommandEnabled(IDS_BOOMARK_BAR_OPEN_ALL_INCOGNITO)); + EXPECT_FALSE(controller.IsCommandEnabled(IDS_BOOKMARK_BAR_REMOVE)); + EXPECT_FALSE( + controller.IsCommandEnabled(IDS_BOOKMARK_MANAGER_SHOW_IN_FOLDER)); + EXPECT_TRUE( + controller.IsCommandEnabled(IDS_BOOMARK_BAR_ADD_NEW_BOOKMARK)); + EXPECT_TRUE( + controller.IsCommandEnabled(IDS_BOOMARK_BAR_NEW_FOLDER)); +} + +// Tests the enabled state of the menus when supplied a vector with a single +// url. +TEST_F(BookmarkContextMenuTest, SingleURL) { + std::vector<BookmarkNode*> nodes; + nodes.push_back(model_->GetBookmarkBarNode()->GetChild(0)); + BookmarkContextMenu controller( + NULL, profile_.get(), NULL, NULL, nodes[0]->GetParent(), + nodes, BookmarkContextMenu::BOOKMARK_BAR); + EXPECT_TRUE(controller.IsCommandEnabled(IDS_BOOMARK_BAR_OPEN_ALL)); + EXPECT_TRUE( + controller.IsCommandEnabled(IDS_BOOMARK_BAR_OPEN_ALL_NEW_WINDOW)); + EXPECT_TRUE(controller.IsCommandEnabled(IDS_BOOMARK_BAR_OPEN_ALL_INCOGNITO)); + EXPECT_TRUE(controller.IsCommandEnabled(IDS_BOOKMARK_BAR_REMOVE)); + EXPECT_FALSE( + controller.IsCommandEnabled(IDS_BOOKMARK_MANAGER_SHOW_IN_FOLDER)); + EXPECT_TRUE( + controller.IsCommandEnabled(IDS_BOOMARK_BAR_ADD_NEW_BOOKMARK)); + EXPECT_TRUE( + controller.IsCommandEnabled(IDS_BOOMARK_BAR_NEW_FOLDER)); +} + +// Tests the enabled state of the menus when supplied a vector with multiple +// urls. +TEST_F(BookmarkContextMenuTest, MultipleURLs) { + std::vector<BookmarkNode*> nodes; + nodes.push_back(model_->GetBookmarkBarNode()->GetChild(0)); + nodes.push_back(model_->GetBookmarkBarNode()->GetChild(1)->GetChild(0)); + BookmarkContextMenu controller( + NULL, profile_.get(), NULL, NULL, nodes[0]->GetParent(), + nodes, BookmarkContextMenu::BOOKMARK_BAR); + EXPECT_TRUE(controller.IsCommandEnabled(IDS_BOOMARK_BAR_OPEN_ALL)); + EXPECT_TRUE( + controller.IsCommandEnabled(IDS_BOOMARK_BAR_OPEN_ALL_NEW_WINDOW)); + EXPECT_TRUE(controller.IsCommandEnabled(IDS_BOOMARK_BAR_OPEN_ALL_INCOGNITO)); + EXPECT_TRUE(controller.IsCommandEnabled(IDS_BOOKMARK_BAR_REMOVE)); + EXPECT_FALSE( + controller.IsCommandEnabled(IDS_BOOKMARK_MANAGER_SHOW_IN_FOLDER)); + EXPECT_TRUE( + controller.IsCommandEnabled(IDS_BOOMARK_BAR_ADD_NEW_BOOKMARK)); + EXPECT_TRUE( + controller.IsCommandEnabled(IDS_BOOMARK_BAR_NEW_FOLDER)); +} + +// Tests the enabled state of the menus when supplied an vector with a single +// folder. +TEST_F(BookmarkContextMenuTest, SingleFolder) { + std::vector<BookmarkNode*> nodes; + nodes.push_back(model_->GetBookmarkBarNode()->GetChild(2)); + BookmarkContextMenu controller( + NULL, profile_.get(), NULL, NULL, nodes[0]->GetParent(), + nodes, BookmarkContextMenu::BOOKMARK_BAR); + EXPECT_FALSE(controller.IsCommandEnabled(IDS_BOOMARK_BAR_OPEN_ALL)); + EXPECT_FALSE( + controller.IsCommandEnabled(IDS_BOOMARK_BAR_OPEN_ALL_NEW_WINDOW)); + EXPECT_FALSE(controller.IsCommandEnabled(IDS_BOOMARK_BAR_OPEN_ALL_INCOGNITO)); + EXPECT_TRUE(controller.IsCommandEnabled(IDS_BOOKMARK_BAR_REMOVE)); + EXPECT_FALSE( + controller.IsCommandEnabled(IDS_BOOKMARK_MANAGER_SHOW_IN_FOLDER)); + EXPECT_TRUE( + controller.IsCommandEnabled(IDS_BOOMARK_BAR_ADD_NEW_BOOKMARK)); + EXPECT_TRUE( + controller.IsCommandEnabled(IDS_BOOMARK_BAR_NEW_FOLDER)); +} + +// Tests the enabled state of the menus when supplied a vector with multiple +// folders, all of which are empty. +TEST_F(BookmarkContextMenuTest, MultipleEmptyFolders) { + std::vector<BookmarkNode*> nodes; + nodes.push_back(model_->GetBookmarkBarNode()->GetChild(2)); + nodes.push_back(model_->GetBookmarkBarNode()->GetChild(3)); + BookmarkContextMenu controller( + NULL, profile_.get(), NULL, NULL, nodes[0]->GetParent(), + nodes, BookmarkContextMenu::BOOKMARK_BAR); + EXPECT_FALSE(controller.IsCommandEnabled(IDS_BOOMARK_BAR_OPEN_ALL)); + EXPECT_FALSE( + controller.IsCommandEnabled(IDS_BOOMARK_BAR_OPEN_ALL_NEW_WINDOW)); + EXPECT_FALSE(controller.IsCommandEnabled(IDS_BOOMARK_BAR_OPEN_ALL_INCOGNITO)); + EXPECT_TRUE(controller.IsCommandEnabled(IDS_BOOKMARK_BAR_REMOVE)); + EXPECT_FALSE( + controller.IsCommandEnabled(IDS_BOOKMARK_MANAGER_SHOW_IN_FOLDER)); + EXPECT_TRUE( + controller.IsCommandEnabled(IDS_BOOMARK_BAR_ADD_NEW_BOOKMARK)); + EXPECT_TRUE( + controller.IsCommandEnabled(IDS_BOOMARK_BAR_NEW_FOLDER)); +} + +// Tests the enabled state of the menus when supplied a vector with multiple +// folders, some of which contain URLs. +TEST_F(BookmarkContextMenuTest, MultipleFoldersWithURLs) { + std::vector<BookmarkNode*> nodes; + nodes.push_back(model_->GetBookmarkBarNode()->GetChild(3)); + nodes.push_back(model_->GetBookmarkBarNode()->GetChild(4)); + BookmarkContextMenu controller( + NULL, profile_.get(), NULL, NULL, nodes[0]->GetParent(), + nodes, BookmarkContextMenu::BOOKMARK_BAR); + EXPECT_TRUE(controller.IsCommandEnabled(IDS_BOOMARK_BAR_OPEN_ALL)); + EXPECT_TRUE( + controller.IsCommandEnabled(IDS_BOOMARK_BAR_OPEN_ALL_NEW_WINDOW)); + EXPECT_TRUE(controller.IsCommandEnabled(IDS_BOOMARK_BAR_OPEN_ALL_INCOGNITO)); + EXPECT_TRUE(controller.IsCommandEnabled(IDS_BOOKMARK_BAR_REMOVE)); + EXPECT_FALSE( + controller.IsCommandEnabled(IDS_BOOKMARK_MANAGER_SHOW_IN_FOLDER)); + EXPECT_TRUE( + controller.IsCommandEnabled(IDS_BOOMARK_BAR_ADD_NEW_BOOKMARK)); + EXPECT_TRUE( + controller.IsCommandEnabled(IDS_BOOMARK_BAR_NEW_FOLDER)); +} + +// Tests the enabled state of open incognito. +TEST_F(BookmarkContextMenuTest, DisableIncognito) { + std::vector<BookmarkNode*> nodes; + nodes.push_back(model_->GetBookmarkBarNode()->GetChild(0)); + BookmarkContextMenu controller( + NULL, profile_.get(), NULL, NULL, nodes[0]->GetParent(), + nodes, BookmarkContextMenu::BOOKMARK_BAR); + profile_->set_off_the_record(true); + EXPECT_FALSE(controller.IsCommandEnabled(IDS_BOOMARK_BAR_OPEN_INCOGNITO)); + EXPECT_FALSE(controller.IsCommandEnabled(IDS_BOOMARK_BAR_OPEN_ALL_INCOGNITO)); +} + +// Tests that you can't remove/edit when showing the other node. +TEST_F(BookmarkContextMenuTest, DisabledItemsWithOtherNode) { + std::vector<BookmarkNode*> nodes; + nodes.push_back(model_->other_node()); + BookmarkContextMenu controller( + NULL, profile_.get(), NULL, NULL, nodes[0], nodes, + BookmarkContextMenu::BOOKMARK_BAR); + EXPECT_FALSE(controller.IsCommandEnabled(IDS_BOOKMARK_BAR_EDIT)); + EXPECT_FALSE(controller.IsCommandEnabled(IDS_BOOKMARK_BAR_REMOVE)); +} diff --git a/chrome/browser/bookmarks/bookmark_drag_utils.cc b/chrome/browser/bookmarks/bookmark_drag_utils.cc deleted file mode 100644 index 863369c..0000000 --- a/chrome/browser/bookmarks/bookmark_drag_utils.cc +++ /dev/null @@ -1,91 +0,0 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/bookmarks/bookmark_drag_utils.h" - -#include "chrome/browser/bookmarks/bookmark_drag_data.h" -#include "chrome/browser/bookmarks/bookmark_model.h" -#include "chrome/common/drag_drop_types.h" -#include "chrome/views/event.h" - -namespace { - -void CloneDragDataImpl(BookmarkModel* model, - const BookmarkDragData::Element& element, - BookmarkNode* parent, - int index_to_add_at) { - if (element.is_url) { - model->AddURL(parent, index_to_add_at, element.title, element.url); - } else { - BookmarkNode* new_folder = model->AddGroup(parent, index_to_add_at, - element.title); - for (int i = 0; i < static_cast<int>(element.children.size()); ++i) - CloneDragDataImpl(model, element.children[i], new_folder, i); - } -} - -} // namespace - -namespace bookmark_drag_utils { - -int PreferredDropOperation(const views::DropTargetEvent& event, - int operation) { - int common_ops = (event.GetSourceOperations() & operation); - if (!common_ops) - return 0; - if (DragDropTypes::DRAG_COPY & common_ops) - return DragDropTypes::DRAG_COPY; - if (DragDropTypes::DRAG_LINK & common_ops) - return DragDropTypes::DRAG_LINK; - if (DragDropTypes::DRAG_MOVE & common_ops) - return DragDropTypes::DRAG_MOVE; - return DragDropTypes::DRAG_NONE; -} - -bool IsValidDropLocation(Profile* profile, - const BookmarkDragData& data, - BookmarkNode* drop_parent, - int index) { - if (!drop_parent->is_folder()) { - NOTREACHED(); - return false; - } - - if (!data.is_valid()) - return false; - - if (data.IsFromProfile(profile)) { - std::vector<BookmarkNode*> nodes = data.GetNodes(profile); - for (size_t i = 0; i < nodes.size(); ++i) { - // Don't allow the drop if the user is attempting to drop on one of the - // nodes being dragged. - BookmarkNode* node = nodes[i]; - int node_index = (drop_parent == node->GetParent()) ? - drop_parent->IndexOfChild(nodes[i]) : -1; - if (node_index != -1 && (index == node_index || index == node_index + 1)) - return false; - - // drop_parent can't accept a child that is an ancestor. - if (drop_parent->HasAncestor(node)) - return false; - } - return true; - } - // From the same profile, always accept. - return true; -} - -void CloneDragData(BookmarkModel* model, - const std::vector<BookmarkDragData::Element>& elements, - BookmarkNode* parent, - int index_to_add_at) { - if (!parent->is_folder() || !model) { - NOTREACHED(); - return; - } - for (size_t i = 0; i < elements.size(); ++i) - CloneDragDataImpl(model, elements[i], parent, index_to_add_at + i); -} - -} // namespace bookmark_drag_utils diff --git a/chrome/browser/bookmarks/bookmark_folder_tree_model.cc b/chrome/browser/bookmarks/bookmark_folder_tree_model.cc index f365e76..b1932a4 100644 --- a/chrome/browser/bookmarks/bookmark_folder_tree_model.cc +++ b/chrome/browser/bookmarks/bookmark_folder_tree_model.cc @@ -33,6 +33,8 @@ BookmarkFolderTreeModel::NodeType BookmarkFolderTreeModel::GetNodeType( return RECENTLY_BOOKMARKED; if (node == search_node_) return SEARCH; + if (node == GetRoot()) + return NONE; return BOOKMARK; } diff --git a/chrome/browser/bookmarks/bookmark_utils.cc b/chrome/browser/bookmarks/bookmark_utils.cc new file mode 100644 index 0000000..d9b0be1 --- /dev/null +++ b/chrome/browser/bookmarks/bookmark_utils.cc @@ -0,0 +1,241 @@ +// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/bookmarks/bookmark_utils.h" + +#include "chrome/browser/bookmarks/bookmark_drag_data.h" +#include "chrome/browser/bookmarks/bookmark_model.h" +#include "chrome/browser/browser.h" +#include "chrome/browser/browser_list.h" +#include "chrome/browser/page_navigator.h" +#include "chrome/browser/tab_contents.h" +#include "chrome/common/drag_drop_types.h" +#include "chrome/common/l10n_util.h" +#include "chrome/views/event.h" + +#include "chromium_strings.h" +#include "generated_resources.h" + +namespace { + +// Number of bookmarks we'll open before prompting the user to see if they +// really want to open all. +const int kNumURLsBeforePrompting = 15; + +// A PageNavigator implementation that creates a new Browser. This is used when +// opening a url and there is no Browser open. The Browser is created the first +// time the PageNavigator method is invoked. +class NewBrowserPageNavigator : public PageNavigator { + public: + explicit NewBrowserPageNavigator(Profile* profile) + : profile_(profile), + browser_(NULL) {} + + virtual ~NewBrowserPageNavigator() { + if (browser_) + browser_->Show(); + } + + Browser* browser() const { return browser_; } + + virtual void OpenURL(const GURL& url, + const GURL& referrer, + WindowOpenDisposition disposition, + PageTransition::Type transition) { + if (!browser_) { + Profile* profile = (disposition == OFF_THE_RECORD) ? + profile_->GetOffTheRecordProfile() : profile_; + browser_ = new Browser(gfx::Rect(), SW_SHOW, profile, + BrowserType::TABBED_BROWSER, std::wstring()); + // Always open the first tab in the foreground. + disposition = NEW_FOREGROUND_TAB; + } + browser_->OpenURLFromTab(NULL, url, referrer, NEW_FOREGROUND_TAB, transition); + } + + private: + Profile* profile_; + Browser* browser_; + + DISALLOW_COPY_AND_ASSIGN(NewBrowserPageNavigator); +}; + +void CloneDragDataImpl(BookmarkModel* model, + const BookmarkDragData::Element& element, + BookmarkNode* parent, + int index_to_add_at) { + if (element.is_url) { + model->AddURL(parent, index_to_add_at, element.title, element.url); + } else { + BookmarkNode* new_folder = model->AddGroup(parent, index_to_add_at, + element.title); + for (int i = 0; i < static_cast<int>(element.children.size()); ++i) + CloneDragDataImpl(model, element.children[i], new_folder, i); + } +} + +// Returns the number of descendants of node that are of type url. +int DescendantURLCount(BookmarkNode* node) { + int result = 0; + for (int i = 0; i < node->GetChildCount(); ++i) { + BookmarkNode* child = node->GetChild(i); + if (child->is_url()) + result++; + else + result += DescendantURLCount(child); + } + return result; +} + +// Implementation of OpenAll. Opens all nodes of type URL and recurses for +// groups. |navigator| is the PageNavigator used to open URLs. After the first +// url is opened |opened_url| is set to true and |navigator| is set to the +// PageNavigator of the last active tab. This is done to handle a window +// disposition of new window, in which case we want subsequent tabs to open in +// that window. +void OpenAllImpl(BookmarkNode* node, + WindowOpenDisposition initial_disposition, + PageNavigator** navigator, + bool* opened_url) { + if (node->is_url()) { + WindowOpenDisposition disposition; + if (*opened_url) + disposition = NEW_BACKGROUND_TAB; + else + disposition = initial_disposition; + (*navigator)->OpenURL(node->GetURL(), GURL(), disposition, + PageTransition::AUTO_BOOKMARK); + if (!*opened_url) { + *opened_url = true; + // We opened the first URL which may have opened a new window or clobbered + // the current page, reset the navigator just to be sure. + Browser* new_browser = BrowserList::GetLastActive(); + if (new_browser) { + TabContents* current_tab = new_browser->GetSelectedTabContents(); + DCHECK(new_browser && current_tab); + if (new_browser && current_tab) + *navigator = current_tab; + } // else, new_browser == NULL, which happens during testing. + } + } else { + // Group, recurse through children. + for (int i = 0; i < node->GetChildCount(); ++i) { + OpenAllImpl(node->GetChild(i), initial_disposition, navigator, + opened_url); + } + } +} + +bool ShouldOpenAll(HWND parent, const std::vector<BookmarkNode*>& nodes) { + int descendant_count = 0; + for (size_t i = 0; i < nodes.size(); ++i) + descendant_count += DescendantURLCount(nodes[i]); + if (descendant_count < kNumURLsBeforePrompting) + return true; + + std::wstring message = + l10n_util::GetStringF(IDS_BOOKMARK_BAR_SHOULD_OPEN_ALL, + IntToWString(descendant_count)); + return MessageBox(parent, message.c_str(), + l10n_util::GetString(IDS_PRODUCT_NAME).c_str(), + MB_YESNO | MB_ICONWARNING | MB_TOPMOST) == IDYES; +} + +} // namespace + +namespace bookmark_utils { + +int PreferredDropOperation(const views::DropTargetEvent& event, + int operation) { + int common_ops = (event.GetSourceOperations() & operation); + if (!common_ops) + return 0; + if (DragDropTypes::DRAG_COPY & common_ops) + return DragDropTypes::DRAG_COPY; + if (DragDropTypes::DRAG_LINK & common_ops) + return DragDropTypes::DRAG_LINK; + if (DragDropTypes::DRAG_MOVE & common_ops) + return DragDropTypes::DRAG_MOVE; + return DragDropTypes::DRAG_NONE; +} + +bool IsValidDropLocation(Profile* profile, + const BookmarkDragData& data, + BookmarkNode* drop_parent, + int index) { + if (!drop_parent->is_folder()) { + NOTREACHED(); + return false; + } + + if (!data.is_valid()) + return false; + + if (data.IsFromProfile(profile)) { + std::vector<BookmarkNode*> nodes = data.GetNodes(profile); + for (size_t i = 0; i < nodes.size(); ++i) { + // Don't allow the drop if the user is attempting to drop on one of the + // nodes being dragged. + BookmarkNode* node = nodes[i]; + int node_index = (drop_parent == node->GetParent()) ? + drop_parent->IndexOfChild(nodes[i]) : -1; + if (node_index != -1 && (index == node_index || index == node_index + 1)) + return false; + + // drop_parent can't accept a child that is an ancestor. + if (drop_parent->HasAncestor(node)) + return false; + } + return true; + } + // From the same profile, always accept. + return true; +} + +void CloneDragData(BookmarkModel* model, + const std::vector<BookmarkDragData::Element>& elements, + BookmarkNode* parent, + int index_to_add_at) { + if (!parent->is_folder() || !model) { + NOTREACHED(); + return; + } + for (size_t i = 0; i < elements.size(); ++i) + CloneDragDataImpl(model, elements[i], parent, index_to_add_at + i); +} + +void OpenAll(HWND parent, + Profile* profile, + PageNavigator* navigator, + const std::vector<BookmarkNode*>& nodes, + WindowOpenDisposition initial_disposition) { + if (!ShouldOpenAll(parent, nodes)) + return; + + NewBrowserPageNavigator navigator_impl(profile); + if (!navigator) { + Browser* browser = + BrowserList::FindBrowserWithType(profile, BrowserType::TABBED_BROWSER); + if (!browser || !browser->GetSelectedTabContents()) + navigator = &navigator_impl; + else + navigator = browser->GetSelectedTabContents(); + } + + bool opened_url = false; + for (size_t i = 0; i < nodes.size(); ++i) + OpenAllImpl(nodes[i], initial_disposition, &navigator, &opened_url); +} + +void OpenAll(HWND parent, + Profile* profile, + PageNavigator* navigator, + BookmarkNode* node, + WindowOpenDisposition initial_disposition) { + std::vector<BookmarkNode*> nodes; + nodes.push_back(node); + OpenAll(parent, profile, navigator, nodes, initial_disposition); +} + +} // namespace bookmark_utils diff --git a/chrome/browser/bookmarks/bookmark_drag_utils.h b/chrome/browser/bookmarks/bookmark_utils.h index 2805311..0711638 100644 --- a/chrome/browser/bookmarks/bookmark_drag_utils.h +++ b/chrome/browser/bookmarks/bookmark_utils.h @@ -2,21 +2,25 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef CHROME_BROWSER_BOOKMARKS_BOOKMARK_DRAG_UTILS_H_ -#define CHROME_BROWSER_BOOKMARKS_BOOKMARK_DRAG_UTILS_H_ +#ifndef CHROME_BROWSER_BOOKMARKS_BOOKMARK_UTILS_H_ +#define CHROME_BROWSER_BOOKMARKS_BOOKMARK_UTILS_H_ + +#include <vector> #include "chrome/browser/bookmarks/bookmark_drag_data.h" +#include "webkit/glue/window_open_disposition.h" class BookmarkNode; +class PageNavigator; class Profile; namespace views { class DropTargetEvent; } -// Functions used in managing bookmark drag and drop. These functions are -// used by both the bookmark bar and bookmark manager. -namespace bookmark_drag_utils { +// A collection of bookmark utility functions used by various parts of the UI +// that show bookmarks: bookmark manager, bookmark bar view ... +namespace bookmark_utils { // Calculates the drop operation given the event and supported set of // operations. This prefers the following ordering: COPY, LINK then MOVE. @@ -40,6 +44,24 @@ void CloneDragData(BookmarkModel* model, BookmarkNode* parent, int index_to_add_at); -} +// Recursively opens all bookmarks. |initial_disposition| dictates how the +// first URL is opened, all subsequent URLs are opened as background tabs. +// |navigator| is used to open the URLs. If |navigator| is NULL the last +// tabbed browser with the profile |profile| is used. If there is no browser +// with the specified profile a new one is created. +void OpenAll(HWND parent, + Profile* profile, + PageNavigator* navigator, + const std::vector<BookmarkNode*>& nodes, + WindowOpenDisposition initial_disposition); + +// Convenience for opening a single BookmarkNode. +void OpenAll(HWND parent, + Profile* profile, + PageNavigator* navigator, + BookmarkNode* node, + WindowOpenDisposition initial_disposition); + +} // namespace bookmark_utils -#endif // CHROME_BROWSER_BOOKMARKS_BOOKMARK_DRAG_UTILS_H_ +#endif // CHROME_BROWSER_BOOKMARKS_BOOKMARK_UTILS_H_ |