summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/bookmark_bar_context_menu_controller.cc397
-rw-r--r--chrome/browser/bookmark_bar_context_menu_controller.h86
-rw-r--r--chrome/browser/bookmark_bar_context_menu_controller_test.cc164
-rw-r--r--chrome/browser/browser.vcproj8
-rw-r--r--chrome/browser/views/bookmark_bar_view.cc387
-rw-r--r--chrome/browser/views/bookmark_bar_view.h35
-rw-r--r--chrome/test/unit/unittests.vcproj8
7 files changed, 694 insertions, 391 deletions
diff --git a/chrome/browser/bookmark_bar_context_menu_controller.cc b/chrome/browser/bookmark_bar_context_menu_controller.cc
new file mode 100644
index 0000000..75bd4fb
--- /dev/null
+++ b/chrome/browser/bookmark_bar_context_menu_controller.cc
@@ -0,0 +1,397 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "chrome/browser/bookmark_bar_context_menu_controller.h"
+
+#include "chrome/browser/bookmark_bar_model.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/user_metrics.h"
+#include "chrome/browser/views/bookmark_editor_view.h"
+#include "chrome/browser/views/input_window.h"
+#include "chrome/common/pref_names.h"
+#include "chrome/common/pref_service.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(BookmarkBarNode* node) {
+ if (node->GetType() == history::StarredEntry::URL)
+ return true;
+
+ for (int i = 0; i < node->GetChildCount(); ++i) {
+ if (NodeHasURLs(node->GetChild(i)))
+ return true;
+ }
+ return false;
+}
+
+// Opens a tab/window for node and recursively opens all descendants.
+// If open_first_in_new_window is true, the first opened node is opened
+// in a new window. navigator indicates the PageNavigator to use for
+// new tabs. It is reset if open_first_in_new_window is true.
+// opened_url is set to true the first time a new tab is opened.
+void OpenAll(BookmarkBarNode* node,
+ bool open_first_in_new_window,
+ PageNavigator** navigator,
+ bool* opened_url) {
+ if (node->GetType() == history::StarredEntry::URL) {
+ WindowOpenDisposition disposition;
+ if (*opened_url)
+ disposition = NEW_BACKGROUND_TAB;
+ else if (open_first_in_new_window)
+ disposition = NEW_WINDOW;
+ else // Open in current window.
+ disposition = CURRENT_TAB;
+ (*navigator)->OpenURL(node->GetURL(), disposition,
+ PageTransition::AUTO_BOOKMARK);
+ if (!*opened_url) {
+ *opened_url = true;
+ if (open_first_in_new_window || disposition == CURRENT_TAB) {
+ // We opened the tab in a new window or in the current tab which
+ // likely reset the navigator. Need to reset the page navigator
+ // appropriately.
+ 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) {
+ OpenAll(node->GetChild(i), open_first_in_new_window, navigator,
+ opened_url);
+ }
+ }
+}
+
+// EditFolderController -------------------------------------------------------
+
+// EditFolderController manages the editing and/or creation of a folder. If the
+// user presses ok, the name change is committed to the database.
+//
+// EditFolderController deletes itself when the window is closed.
+//
+class EditFolderController : public InputWindowDelegate,
+ public BookmarkBarView::ModelChangedListener {
+ public:
+ EditFolderController(BookmarkBarView* view,
+ BookmarkBarNode* node,
+ int visual_order,
+ bool is_new)
+ : view_(view),
+ node_(node),
+ visual_order_(visual_order),
+ is_new_(is_new) {
+ DCHECK(is_new_ || node);
+ window_ = CreateInputWindow(view->GetViewContainer()->GetHWND(), this);
+ view_->SetModelChangedListener(this);
+ }
+
+ void Show() {
+ window_->Show();
+ }
+
+ virtual void ModelChanged() {
+ window_->Close();
+ }
+
+ private:
+ 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) {
+ view_->ClearModelChangedListenerIfEquals(this);
+ BookmarkBarModel* model = view_->GetProfile()->GetBookmarkBarModel();
+ if (is_new_)
+ model->AddGroup(node_, visual_order_, text);
+ else
+ model->SetTitle(node_, text);
+ }
+
+ virtual void InputCanceled() {
+ view_->ClearModelChangedListenerIfEquals(this);
+ }
+
+ virtual void WindowClosing() {
+ view_->ClearModelChangedListenerIfEquals(this);
+ 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);
+ }
+
+ virtual ChromeViews::View* GetContentsView() {
+ return view_;
+ }
+
+ BookmarkBarView* view_;
+
+ // 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.
+ BookmarkBarNode* node_;
+
+ int visual_order_;
+ bool is_new_;
+ ChromeViews::Window* window_;
+
+ DISALLOW_EVIL_CONSTRUCTORS(EditFolderController);
+};
+
+} // namespace
+
+// BookmarkBarContextMenuController -------------------------------------------
+
+const int BookmarkBarContextMenuController::always_show_command_id = 1;
+const int BookmarkBarContextMenuController::open_bookmark_id = 2;
+const int BookmarkBarContextMenuController::open_bookmark_in_new_window_id = 3;
+const int BookmarkBarContextMenuController::open_bookmark_in_new_tab_id = 4;
+const int BookmarkBarContextMenuController::open_all_bookmarks_id = 5;
+const int
+ BookmarkBarContextMenuController::open_all_bookmarks_in_new_window_id = 6;
+const int BookmarkBarContextMenuController::edit_bookmark_id = 7;
+const int BookmarkBarContextMenuController::delete_bookmark_id = 8;
+const int BookmarkBarContextMenuController::add_bookmark_id = 9;
+const int BookmarkBarContextMenuController::new_folder_id = 10;
+
+BookmarkBarContextMenuController::BookmarkBarContextMenuController(
+ BookmarkBarView* view,
+ BookmarkBarNode* node)
+ : view_(view),
+ node_(node),
+ menu_(this) {
+ if (node->GetType() == history::StarredEntry::URL) {
+ menu_.AppendMenuItemWithLabel(
+ open_bookmark_id,
+ l10n_util::GetString(IDS_BOOMARK_BAR_OPEN));
+ menu_.AppendMenuItemWithLabel(
+ open_bookmark_in_new_tab_id,
+ l10n_util::GetString(IDS_BOOMARK_BAR_OPEN_IN_NEW_TAB));
+ menu_.AppendMenuItemWithLabel(
+ open_bookmark_in_new_window_id,
+ l10n_util::GetString(IDS_BOOMARK_BAR_OPEN_IN_NEW_WINDOW));
+ } else {
+ menu_.AppendMenuItemWithLabel(
+ open_all_bookmarks_id,
+ l10n_util::GetString(IDS_BOOMARK_BAR_OPEN_ALL));
+ menu_.AppendMenuItemWithLabel(
+ open_all_bookmarks_in_new_window_id,
+ l10n_util::GetString(IDS_BOOMARK_BAR_OPEN_ALL_NEW_WINDOW));
+ }
+ menu_.AppendSeparator();
+
+ if (node->GetParent() !=
+ view->GetProfile()->GetBookmarkBarModel()->root_node()) {
+ menu_.AppendMenuItemWithLabel(edit_bookmark_id,
+ l10n_util::GetString(IDS_BOOKMARK_BAR_EDIT));
+ menu_.AppendMenuItemWithLabel(
+ delete_bookmark_id,
+ l10n_util::GetString(IDS_BOOKMARK_BAR_REMOVE));
+ }
+
+ menu_.AppendMenuItemWithLabel(
+ add_bookmark_id,
+ l10n_util::GetString(IDS_BOOMARK_BAR_ADD_NEW_BOOKMARK));
+ menu_.AppendMenuItemWithLabel(
+ new_folder_id,
+ l10n_util::GetString(IDS_BOOMARK_BAR_NEW_FOLDER));
+ menu_.AppendSeparator();
+ menu_.AppendMenuItem(always_show_command_id,
+ l10n_util::GetString(IDS_BOOMARK_BAR_ALWAYS_SHOW),
+ ChromeViews::MenuItemView::CHECKBOX);
+}
+
+void BookmarkBarContextMenuController::RunMenuAt(int x, int y) {
+ // Record the current ModelChangedListener. It will be non-null when we're
+ // used as the context menu for another menu.
+ ModelChangedListener* last_listener = view_->GetModelChangedListener();
+
+ view_->SetModelChangedListener(this);
+
+ // width/height don't matter here.
+ menu_.RunMenuAt(view_->GetViewContainer()->GetHWND(), gfx::Rect(x, y, 0, 0),
+ ChromeViews::MenuItemView::TOPLEFT, false);
+
+ if (view_->GetModelChangedListener() == this)
+ view_->SetModelChangedListener(last_listener);
+}
+
+void BookmarkBarContextMenuController::ModelChanged() {
+ menu_.Cancel();
+}
+
+void BookmarkBarContextMenuController::ExecuteCommand(int id) {
+ Profile* profile = view_->GetProfile();
+
+ switch (id) {
+ case open_bookmark_id:
+ UserMetrics::RecordAction(L"BookmarkBar_ContextMenu_Open", profile);
+
+ view_->GetPageNavigator()->OpenURL(node_->GetURL(), CURRENT_TAB,
+ PageTransition::AUTO_BOOKMARK);
+ break;
+
+ case open_bookmark_in_new_window_id:
+ UserMetrics::RecordAction(L"BookmarkBar_ContextMenu_OpenInNewWindow",
+ profile);
+
+ view_->GetPageNavigator()->OpenURL(node_->GetURL(), NEW_WINDOW,
+ PageTransition::AUTO_BOOKMARK);
+ break;
+
+ case open_bookmark_in_new_tab_id:
+ UserMetrics::RecordAction(L"BookmarkBar_ContextMenu_OpenInNewTab",
+ profile);
+
+ view_->GetPageNavigator()->OpenURL(node_->GetURL(), NEW_FOREGROUND_TAB,
+ PageTransition::AUTO_BOOKMARK);
+ break;
+
+ case open_all_bookmarks_id:
+ case open_all_bookmarks_in_new_window_id: {
+ if (id == open_all_bookmarks_id) {
+ UserMetrics::RecordAction(L"BookmarkBar_ContextMenu_OpenAll",
+ profile);
+ } else {
+ UserMetrics::RecordAction(
+ L"BookmarkBar_ContextMenu_OpenAllInNewWindow", profile);
+ }
+
+ BookmarkBarNode* node = node_;
+ PageNavigator* navigator = view_->GetPageNavigator();
+ bool opened_url = false;
+ OpenAll(node, (id == open_all_bookmarks_in_new_window_id), &navigator,
+ &opened_url);
+ break;
+ }
+
+ case edit_bookmark_id:
+ UserMetrics::RecordAction(L"BookmarkBar_ContextMenu_Edit", profile);
+
+ if (node_->GetType() == history::StarredEntry::URL) {
+ BookmarkEditorView::Show(view_->GetViewContainer()->GetHWND(),
+ view_->GetProfile(), node_->GetURL(),
+ node_->GetTitle());
+ } else {
+ // Controller deletes itself when done.
+ EditFolderController* controller = new EditFolderController(
+ view_, node_, -1, false);
+ controller->Show();
+ }
+ break;
+
+ case delete_bookmark_id: {
+ UserMetrics::RecordAction(L"BookmarkBar_ContextMenu_Remove", profile);
+
+ view_->GetModel()->Remove(node_->GetParent(),
+ node_->GetParent()->IndexOfChild(node_));
+ break;
+ }
+
+ case add_bookmark_id: {
+ UserMetrics::RecordAction(L"BookmarkBar_ContextMenu_Add", profile);
+
+ BookmarkEditorView::Show(view_->GetViewContainer()->GetHWND(),
+ view_->GetProfile(), GURL(), std::wstring());
+ break;
+ }
+
+ case new_folder_id: {
+ UserMetrics::RecordAction(L"BookmarkBar_ContextMenu_NewFolder",
+ profile);
+
+ int visual_order;
+ BookmarkBarNode* parent =
+ GetParentAndVisualOrderForNewNode(&visual_order);
+ GetParentAndVisualOrderForNewNode(&visual_order);
+ // Controller deletes itself when done.
+ EditFolderController* controller =
+ new EditFolderController(view_, parent, visual_order, true);
+ controller->Show();
+ break;
+ }
+
+ case always_show_command_id:
+ view_->ToggleWhenVisible();
+ break;
+
+ default:
+ NOTREACHED();
+ }
+}
+
+bool BookmarkBarContextMenuController::IsItemChecked(int id) const {
+ DCHECK(id == always_show_command_id);
+ return view_->GetProfile()->GetPrefs()->GetBoolean(prefs::kShowBookmarkBar);
+}
+
+bool BookmarkBarContextMenuController::IsCommandEnabled(int id) const {
+ if (id == open_all_bookmarks_id || id == open_all_bookmarks_in_new_window_id)
+ return NodeHasURLs(node_);
+
+ return true;
+}
+
+// Returns the parent node and visual_order to use when adding new
+// bookmarks/folders.
+BookmarkBarNode* BookmarkBarContextMenuController::
+ GetParentAndVisualOrderForNewNode(int* visual_order) {
+ if (node_->GetType() != history::StarredEntry::URL) {
+ // Adding to a group always adds to the end.
+ *visual_order = node_->GetChildCount();
+ return node_;
+ } else {
+ DCHECK(node_->GetParent());
+ *visual_order = node_->GetParent()->IndexOfChild(node_) + 1;
+ return node_->GetParent();
+ }
+}
diff --git a/chrome/browser/bookmark_bar_context_menu_controller.h b/chrome/browser/bookmark_bar_context_menu_controller.h
new file mode 100644
index 0000000..28bf329
--- /dev/null
+++ b/chrome/browser/bookmark_bar_context_menu_controller.h
@@ -0,0 +1,86 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef CHROME_BROWSER_BOOKMARK_BAR_CONTEXT_MENU_CONTROLLER_H_
+#define CHROME_BROWSER_BOOKMARK_BAR_CONTEXT_MENU_CONTROLLER_H_
+
+#include "chrome/views/chrome_menu.h"
+#include "chrome/browser/views/bookmark_bar_view.h"
+
+class BookmarkBarNode;
+class PageNavigator;
+
+// BookmarkBarContextMenuController manages the context menus shown for the
+// bookmark bar, items on the bookmark bar, and submens of folders on the
+// bookmark bar.
+class BookmarkBarContextMenuController : public ChromeViews::MenuDelegate,
+ public BookmarkBarView::ModelChangedListener {
+ public:
+ BookmarkBarContextMenuController(BookmarkBarView* view,
+ BookmarkBarNode* node);
+
+ // Shows the menu at the specified place.
+ void RunMenuAt(int x, int y);
+
+ // ModelChangedListener method, cancels the menu.
+ virtual void ModelChanged();
+
+ // Returns the menu.
+ ChromeViews::MenuItemView* menu() { return &menu_; }
+
+ // Menu::Delegate methods.
+ virtual void ExecuteCommand(int id);
+ virtual bool IsItemChecked(int id) const;
+ virtual bool IsCommandEnabled(int id) const;
+
+ // IDs used for the menus. Public for testing.
+ static const int always_show_command_id;
+ static const int open_bookmark_id;
+ static const int open_bookmark_in_new_window_id;
+ static const int open_bookmark_in_new_tab_id;
+ static const int open_all_bookmarks_id;
+ static const int open_all_bookmarks_in_new_window_id;
+ static const int edit_bookmark_id;
+ static const int delete_bookmark_id;
+ static const int add_bookmark_id;
+ static const int new_folder_id;
+
+ private:
+ // Returns the parent node and visual_order to use when adding new
+ // bookmarks/folders.
+ BookmarkBarNode* GetParentAndVisualOrderForNewNode(int* visual_order);
+
+ ChromeViews::MenuItemView menu_;
+ BookmarkBarView* view_;
+ BookmarkBarNode* node_;
+
+ DISALLOW_EVIL_CONSTRUCTORS(BookmarkBarContextMenuController);
+};
+
+#endif // CHROME_BROWSER_BOOKMARK_BAR_CONTEXT_MENU_CONTROLLER_H_
diff --git a/chrome/browser/bookmark_bar_context_menu_controller_test.cc b/chrome/browser/bookmark_bar_context_menu_controller_test.cc
new file mode 100644
index 0000000..a90ea9d
--- /dev/null
+++ b/chrome/browser/bookmark_bar_context_menu_controller_test.cc
@@ -0,0 +1,164 @@
+// Copyright 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#include "chrome/browser/bookmark_bar_context_menu_controller.h"
+#include "chrome/browser/bookmark_bar_model.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"
+
+namespace {
+
+// PageNavigator implementation that records the URL.
+class TestingPageNavigator : public PageNavigator {
+ public:
+ virtual void OpenURL(const GURL& url,
+ WindowOpenDisposition disposition,
+ PageTransition::Type transition) {
+ urls_.push_back(url);
+ }
+
+ std::vector<GURL> urls_;
+};
+
+} // namespace
+
+class BookmarkBarContextMenuControllerTest : public testing::Test {
+ public:
+ BookmarkBarContextMenuControllerTest() : bb_view_(NULL), model_(NULL) {
+ }
+
+ virtual void SetUp() {
+ BookmarkBarView::testing_ = true;
+
+ profile_.reset(new TestingProfile());
+ profile_->set_has_history_service(true);
+ profile_->CreateBookmarkBarModel();
+
+ model_ = profile_->GetBookmarkBarModel();
+
+ bb_view_ = new BookmarkBarView(profile_.get(), NULL);
+ bb_view_->SetPageNavigator(&navigator_);
+
+ AddTestData();
+ }
+
+ virtual void TearDown() {
+ BookmarkBarView::testing_ = false;
+ }
+
+ protected:
+ BookmarkBarModel* model_;
+ BookmarkBarView* bb_view_;
+ TestingPageNavigator navigator_;
+
+ private:
+ // Creates the following structure:
+ // a
+ // F1
+ // f1a
+ // F11
+ // f11a
+ // F2
+ void AddTestData() {
+ std::string test_base = "file:///c:/tmp/";
+
+ model_->AddURL(model_->GetBookmarkBarNode(), 0, L"a",
+ GURL(test_base + "a"));
+ BookmarkBarNode* f1 =
+ model_->AddGroup(model_->GetBookmarkBarNode(), 1, L"F1");
+ model_->AddURL(f1, 0, L"f1a", GURL(test_base + "f1a"));
+ BookmarkBarNode* f11 = model_->AddGroup(f1, 1, L"F11");
+ model_->AddURL(f11, 0, L"f11a", GURL(test_base + "f11a"));
+ model_->AddGroup(model_->GetBookmarkBarNode(), 2, L"F2");
+ }
+
+ scoped_ptr<TestingProfile> profile_;
+};
+
+// Tests Deleting from the menu.
+TEST_F(BookmarkBarContextMenuControllerTest, DeleteURL) {
+ BookmarkBarContextMenuController controller(
+ bb_view_, model_->GetBookmarkBarNode()->GetChild(0));
+ GURL url = model_->GetBookmarkBarNode()->GetChild(0)->GetURL();
+ ASSERT_TRUE(controller.IsCommandEnabled(
+ BookmarkBarContextMenuController::delete_bookmark_id));
+ // Delete the URL.
+ controller.ExecuteCommand(
+ BookmarkBarContextMenuController::delete_bookmark_id);
+ // Model shouldn't have URL anymore.
+ ASSERT_TRUE(model_->GetNodeByURL(url) == NULL);
+}
+
+// Tests openning from the menu.
+TEST_F(BookmarkBarContextMenuControllerTest, OpenURL) {
+ BookmarkBarContextMenuController controller(
+ bb_view_, model_->GetBookmarkBarNode()->GetChild(0));
+ GURL url = model_->GetBookmarkBarNode()->GetChild(0)->GetURL();
+ ASSERT_TRUE(controller.IsCommandEnabled(
+ BookmarkBarContextMenuController::open_bookmark_id));
+ // Open it.
+ controller.ExecuteCommand(
+ BookmarkBarContextMenuController::open_bookmark_id);
+ // Should have navigated to it.
+ ASSERT_EQ(1, navigator_.urls_.size());
+ ASSERT_TRUE(url == navigator_.urls_[0]);
+}
+
+// Tests open all on a folder with a couple of bookmarks.
+TEST_F(BookmarkBarContextMenuControllerTest, OpenAll) {
+ BookmarkBarNode* folder = model_->GetBookmarkBarNode()->GetChild(1);
+ BookmarkBarContextMenuController controller(bb_view_, folder);
+ ASSERT_TRUE(controller.IsCommandEnabled(
+ BookmarkBarContextMenuController::open_all_bookmarks_id));
+ ASSERT_TRUE(controller.IsCommandEnabled(
+ BookmarkBarContextMenuController::open_all_bookmarks_in_new_window_id));
+ // Open it.
+ controller.ExecuteCommand(
+ BookmarkBarContextMenuController::open_all_bookmarks_id);
+ // 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 that menus are appropriately disabled for empty folders.
+TEST_F(BookmarkBarContextMenuControllerTest, DisableForEmptyFolder) {
+ BookmarkBarNode* folder = model_->GetBookmarkBarNode()->GetChild(2);
+ BookmarkBarContextMenuController controller(bb_view_, folder);
+ EXPECT_FALSE(controller.IsCommandEnabled(
+ BookmarkBarContextMenuController::open_all_bookmarks_id));
+ EXPECT_FALSE(controller.IsCommandEnabled(
+ BookmarkBarContextMenuController::open_all_bookmarks_in_new_window_id));
+}
diff --git a/chrome/browser/browser.vcproj b/chrome/browser/browser.vcproj
index 1669c46..98286a1 100644
--- a/chrome/browser/browser.vcproj
+++ b/chrome/browser/browser.vcproj
@@ -802,6 +802,14 @@
Name="Bookmark Bar"
>
<File
+ RelativePath=".\bookmark_bar_context_menu_controller.cc"
+ >
+ </File>
+ <File
+ RelativePath=".\bookmark_bar_context_menu_controller.h"
+ >
+ </File>
+ <File
RelativePath=".\bookmark_bar_model.cc"
>
</File>
diff --git a/chrome/browser/views/bookmark_bar_view.cc b/chrome/browser/views/bookmark_bar_view.cc
index 6579a0f..d249d38 100644
--- a/chrome/browser/views/bookmark_bar_view.cc
+++ b/chrome/browser/views/bookmark_bar_view.cc
@@ -34,6 +34,7 @@
#include "base/base_drag_source.h"
#include "base/gfx/skia_utils.h"
#include "chrome/app/theme/theme_resources.h"
+#include "chrome/browser/bookmark_bar_context_menu_controller.h"
#include "chrome/browser/browser.h"
#include "chrome/browser/browser_list.h"
#include "chrome/browser/browser_process.h"
@@ -326,384 +327,6 @@ struct DropInfo {
BookmarkDragData data;
};
-// ModelChangedListener -------------------------------------------------------
-
-// Interface implemented by controllers/views that need to be notified any
-// time the model changes, typically to cancel an operation that is showing
-// data from the model such as a menu. This isn't intended as a general
-// way to be notified of changes, rather for cases where a controller/view is
-// showing data from the model in a modal like setting and needs to cleanly
-// exit the modal loop if the model changes out from under it.
-//
-// A controller/view that needs this notification should install itself as the
-// ModelChangeListener via the SetModelChangedListener method when shown and
-// reset the ModelChangeListener of the BookmarkBarView when it closes by way
-// of either the SetModelChangedListener method or the
-// ClearModelChangedListenerIfEquals method.
-//
-class ModelChangedListener {
- public:
- virtual ~ModelChangedListener() {}
- // Invoked when the model changes. Should cancel the edit and close any
- // dialogs.
- virtual void ModelChanged() = 0;
-};
-
-// EditFolderController -------------------------------------------------------
-
-// EditFolderController manages the editing and/or creation of a folder. If the
-// user presses ok, the name change is committed to the database.
-//
-// EditFolderController deletes itself when the window is closed.
-//
-class EditFolderController : public InputWindowDelegate,
- public ModelChangedListener {
- public:
- EditFolderController(BookmarkBarView* view,
- BookmarkBarNode* node,
- int visual_order,
- bool is_new)
- : view_(view),
- node_(node),
- visual_order_(visual_order),
- is_new_(is_new) {
- DCHECK(is_new_ || node);
- window_ = CreateInputWindow(view->GetViewContainer()->GetHWND(), this);
- view_->SetModelChangedListener(this);
- }
-
- void Show() {
- window_->Show();
- }
-
- virtual void ModelChanged() {
- window_->Close();
- }
-
- private:
- 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) {
- view_->ClearModelChangedListenerIfEquals(this);
- BookmarkBarModel* model = view_->GetProfile()->GetBookmarkBarModel();
- if (is_new_)
- model->AddGroup(node_, visual_order_, text);
- else
- model->SetTitle(node_, text);
- }
-
- virtual void InputCanceled() {
- view_->ClearModelChangedListenerIfEquals(this);
- }
-
- virtual void WindowClosing() {
- view_->ClearModelChangedListenerIfEquals(this);
- 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);
- }
-
- virtual ChromeViews::View* GetContentsView() {
- return view_;
- }
-
- BookmarkBarView* view_;
-
- // 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.
- BookmarkBarNode* node_;
-
- int visual_order_;
- bool is_new_;
- ChromeViews::Window* window_;
-
- DISALLOW_EVIL_CONSTRUCTORS(EditFolderController);
-};
-
-// BookmarkNodeMenuController -------------------------------------------------
-
-// IDs for the menus we create.
-
-static const int kOpenBookmarkID = 2;
-static const int kOpenBookmarkInNewWindowID = 3;
-static const int kOpenBookmarkInNewTabID = 4;
-static const int kOpenAllBookmarksID = 5;
-static const int kOpenAllBookmarksInNewWindowID = 6;
-static const int kEditBookmarkID = 7;
-static const int kDeleteBookmarkID = 8;
-static const int kAddBookmarkID = 9;
-static const int kNewFolderID = 10;
-
-// BookmarkNodeMenuController manages the context menus shown for the bookmark
-// bar and buttons on the bookmark bar.
-
-class BookmarkNodeMenuController : public ChromeViews::MenuDelegate,
- public ModelChangedListener {
- public:
- BookmarkNodeMenuController(BookmarkBarView* view,
- BookmarkBarNode* node)
- : view_(view),
- node_(node),
- menu_(this) {
- if (node->GetType() == history::StarredEntry::URL) {
- menu_.AppendMenuItemWithLabel(kOpenBookmarkID,
- l10n_util::GetString(IDS_BOOMARK_BAR_OPEN));
- menu_.AppendMenuItemWithLabel(kOpenBookmarkInNewTabID,
- l10n_util::GetString(IDS_BOOMARK_BAR_OPEN_IN_NEW_TAB));
- menu_.AppendMenuItemWithLabel(kOpenBookmarkInNewWindowID,
- l10n_util::GetString(IDS_BOOMARK_BAR_OPEN_IN_NEW_WINDOW));
- } else {
- menu_.AppendMenuItemWithLabel(kOpenAllBookmarksID,
- l10n_util::GetString(IDS_BOOMARK_BAR_OPEN_ALL));
- menu_.AppendMenuItemWithLabel(kOpenAllBookmarksInNewWindowID,
- l10n_util::GetString(IDS_BOOMARK_BAR_OPEN_ALL_NEW_WINDOW));
- }
- menu_.AppendSeparator();
-
- if (node->GetParent() !=
- view->GetProfile()->GetBookmarkBarModel()->root_node()) {
- menu_.AppendMenuItemWithLabel(kEditBookmarkID,
- l10n_util::GetString(IDS_BOOKMARK_BAR_EDIT));
- menu_.AppendMenuItemWithLabel(kDeleteBookmarkID,
- l10n_util::GetString(IDS_BOOKMARK_BAR_REMOVE));
- }
-
- menu_.AppendMenuItemWithLabel(kAddBookmarkID,
- l10n_util::GetString(IDS_BOOMARK_BAR_ADD_NEW_BOOKMARK));
- menu_.AppendMenuItemWithLabel(kNewFolderID,
- l10n_util::GetString(IDS_BOOMARK_BAR_NEW_FOLDER));
- menu_.AppendSeparator();
- menu_.AppendMenuItem(kAlwaysShowCommandID,
- l10n_util::GetString(IDS_BOOMARK_BAR_ALWAYS_SHOW),
- MenuItemView::CHECKBOX);
- }
-
- void RunMenuAt(int x, int y) {
- // Record the current ModelChangedListener. It will be non-null when we're
- // used as the context menu for another menu.
- ModelChangedListener* last_listener = view_->GetModelChangedListener();
-
- view_->SetModelChangedListener(this);
-
- // width/height don't matter here.
- menu_.RunMenuAt(view_->GetViewContainer()->GetHWND(), gfx::Rect(x, y, 0, 0),
- MenuItemView::TOPLEFT, false);
-
- if (view_->GetModelChangedListener() == this)
- view_->SetModelChangedListener(last_listener);
- }
-
- virtual void ModelChanged() {
- menu_.Cancel();
- }
-
- MenuItemView* menu() { return &menu_; }
-
- private:
- // Menu::Delegate method. Does the appropriate operation based on chosen
- // menu item.
- virtual void ExecuteCommand(int id) {
- Profile* profile = view_->GetProfile();
-
- switch (id) {
- case kOpenBookmarkID:
- UserMetrics::RecordAction(L"BookmarkBar_ContextMenu_Open", profile);
-
- view_->GetPageNavigator()->OpenURL(node_->GetURL(), CURRENT_TAB,
- PageTransition::AUTO_BOOKMARK);
- break;
-
- case kOpenBookmarkInNewWindowID:
- UserMetrics::RecordAction(L"BookmarkBar_ContextMenu_OpenInNewWindow",
- profile);
-
- view_->GetPageNavigator()->OpenURL(node_->GetURL(), NEW_WINDOW,
- PageTransition::AUTO_BOOKMARK);
- break;
-
- case kOpenBookmarkInNewTabID:
- UserMetrics::RecordAction(L"BookmarkBar_ContextMenu_OpenInNewTab",
- profile);
-
- view_->GetPageNavigator()->OpenURL(node_->GetURL(), NEW_FOREGROUND_TAB,
- PageTransition::AUTO_BOOKMARK);
- break;
-
- case kOpenAllBookmarksID:
- case kOpenAllBookmarksInNewWindowID: {
- if (id == kOpenAllBookmarksID) {
- UserMetrics::RecordAction(L"BookmarkBar_ContextMenu_OpenAll",
- profile);
- } else {
- UserMetrics::RecordAction(
- L"BookmarkBar_ContextMenu_OpenAllInNewWindow", profile);
- }
-
- BookmarkBarNode* node = node_;
- PageNavigator* navigator = view_->GetPageNavigator();
- bool opened_url = false;
- OpenAll(node, (id == kOpenAllBookmarksInNewWindowID), &navigator,
- &opened_url);
- break;
- }
-
- case kEditBookmarkID:
- UserMetrics::RecordAction(L"BookmarkBar_ContextMenu_Edit", profile);
-
- if (node_->GetType() == history::StarredEntry::URL) {
- BookmarkEditorView::Show(view_->GetViewContainer()->GetHWND(),
- view_->GetProfile(), node_->GetURL(), node_->GetTitle());
- } else {
- // Controller deletes itself when done.
- EditFolderController* controller = new EditFolderController(
- view_, node_, -1, false);
- controller->Show();
- }
- break;
-
- case kDeleteBookmarkID: {
- UserMetrics::RecordAction(L"BookmarkBar_ContextMenu_Remove", profile);
-
- view_->model_->Remove(node_->GetParent(),
- node_->GetParent()->IndexOfChild(node_));
- break;
- }
-
- case kAddBookmarkID: {
- UserMetrics::RecordAction(L"BookmarkBar_ContextMenu_Add", profile);
-
- BookmarkEditorView::Show(view_->GetViewContainer()->GetHWND(),
- view_->GetProfile(), GURL(), std::wstring());
- break;
- }
-
- case kNewFolderID: {
- UserMetrics::RecordAction(L"BookmarkBar_ContextMenu_NewFolder",
- profile);
-
- int visual_order;
- BookmarkBarNode* parent =
- GetParentAndVisualOrderForNewNode(&visual_order);
- GetParentAndVisualOrderForNewNode(&visual_order);
- // Controller deletes itself when done.
- EditFolderController* controller =
- new EditFolderController(view_, parent, visual_order, true);
- controller->Show();
- break;
- }
-
- case kAlwaysShowCommandID:
- view_->ToggleWhenVisible();
- break;
-
- default:
- NOTREACHED();
- }
- }
-
- bool IsItemChecked(int id) const {
- DCHECK(id == kAlwaysShowCommandID);
- return view_->GetProfile()->GetPrefs()->GetBoolean(prefs::kShowBookmarkBar);
- }
-
- // Opens a tab/window for node and recursively opens all descendants.
- // If open_first_in_new_window is true, the first opened node is opened
- // in a new window. navigator indicates the PageNavigator to use for
- // new tabs. It is reset if open_first_in_new_window is true.
- // opened_url is set to true the first time a new tab is opened.
- void OpenAll(BookmarkBarNode* node,
- bool open_first_in_new_window,
- PageNavigator** navigator,
- bool* opened_url) {
- if (node->GetType() == history::StarredEntry::URL) {
- WindowOpenDisposition disposition;
- if (*opened_url)
- disposition = NEW_BACKGROUND_TAB;
- else if (open_first_in_new_window)
- disposition = NEW_WINDOW;
- else // Open in current window.
- disposition = CURRENT_TAB;
- (*navigator)->OpenURL(node->GetURL(), disposition,
- PageTransition::AUTO_BOOKMARK);
- if (!*opened_url) {
- *opened_url = true;
- if (open_first_in_new_window || disposition == CURRENT_TAB) {
- // We opened the tab in a new window or in the current tab which
- // likely reset the navigator. Need to reset the page navigator
- // appropriately.
- Browser* new_browser = BrowserList::GetLastActive();
- TabContents* current_tab = new_browser->GetSelectedTabContents();
- DCHECK(new_browser && current_tab);
- if (new_browser && current_tab)
- *navigator = current_tab;
- }
- }
- } else {
- // Group, recurse through children.
- for (int i = 0; i < node->GetChildCount(); ++i) {
- OpenAll(node->GetChild(i), open_first_in_new_window, navigator,
- opened_url);
- }
- }
- }
-
- virtual bool IsCommandEnabled(int id) const {
- if (id == kOpenAllBookmarksID || id == kOpenAllBookmarksInNewWindowID)
- return NodeHasURLs(node_);
-
- return true;
- }
-
- // Returns true if the specified node is of type URL, or has a descendant
- // of type URL.
- static bool NodeHasURLs(BookmarkBarNode* node) {
- if (node->GetType() == history::StarredEntry::URL)
- return true;
-
- for (int i = 0; i < node->GetChildCount(); ++i) {
- if (NodeHasURLs(node->GetChild(i)))
- return true;
- }
- return false;
- }
-
- // Returns the parent node and visual_order to use when adding new
- // bookmarks/folders.
- BookmarkBarNode* GetParentAndVisualOrderForNewNode(int* visual_order) {
- if (node_->GetType() != history::StarredEntry::URL) {
- // Adding to a group always adds to the end.
- *visual_order = node_->GetChildCount();
- return node_;
- } else {
- DCHECK(node_->GetParent());
- *visual_order = node_->GetParent()->IndexOfChild(node_) + 1;
- return node_->GetParent();
- }
- }
-
- MenuItemView menu_;
- BookmarkBarView* view_;
- BookmarkBarNode* node_;
-
- DISALLOW_EVIL_CONSTRUCTORS(BookmarkNodeMenuController);
-};
-
// MenuRunner -----------------------------------------------------------------
// MenuRunner manages creation and showing of a menu containing BookmarkNodes.
@@ -711,7 +334,7 @@ class BookmarkNodeMenuController : public ChromeViews::MenuDelegate,
// bookmark bar, other folder, or overflow bookmarks.
//
class MenuRunner : public ChromeViews::MenuDelegate,
- public ModelChangedListener {
+ public BookmarkBarView::ModelChangedListener {
public:
// start_child_index is the index of the first child in node to add to the
// menu.
@@ -894,7 +517,7 @@ class MenuRunner : public ChromeViews::MenuDelegate,
bool is_mouse_gesture) {
DCHECK(menu_id_to_node_map_.find(id) != menu_id_to_node_map_.end());
context_menu_.reset(
- new BookmarkNodeMenuController(view_, menu_id_to_node_map_[id]));
+ new BookmarkBarContextMenuController(view_, menu_id_to_node_map_[id]));
context_menu_->RunMenuAt(x, y);
context_menu_.reset(NULL);
}
@@ -942,7 +565,7 @@ class MenuRunner : public ChromeViews::MenuDelegate,
// Data for the drop.
BookmarkDragData drop_data_;
- scoped_ptr<BookmarkNodeMenuController> context_menu_;
+ scoped_ptr<BookmarkBarContextMenuController> context_menu_;
DISALLOW_EVIL_CONSTRUCTORS(MenuRunner);
};
@@ -1788,7 +1411,7 @@ void BookmarkBarView::ShowContextMenu(View* source,
bookmark_button_index < GetBookmarkButtonCount());
node = model_->GetBookmarkBarNode()->GetChild(bookmark_button_index);
}
- BookmarkNodeMenuController controller(this, node);
+ BookmarkBarContextMenuController controller(this, node);
controller.RunMenuAt(x, y);
}
diff --git a/chrome/browser/views/bookmark_bar_view.h b/chrome/browser/views/bookmark_bar_view.h
index 287f8d7..590ab9d 100644
--- a/chrome/browser/views/bookmark_bar_view.h
+++ b/chrome/browser/views/bookmark_bar_view.h
@@ -27,8 +27,8 @@
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#ifndef CHROME_BROWSER_VIEWS_BOOKMARK_BAR_VIEW_H__
-#define CHROME_BROWSER_VIEWS_BOOKMARK_BAR_VIEW_H__
+#ifndef CHROME_BROWSER_VIEWS_BOOKMARK_BAR_VIEW_H_
+#define CHROME_BROWSER_VIEWS_BOOKMARK_BAR_VIEW_H_
#include "chrome/browser/bookmark_bar_model.h"
#include "chrome/browser/bookmark_drag_data.h"
@@ -39,14 +39,11 @@
#include "chrome/views/view.h"
#include "chrome/views/view_menu_delegate.h"
+class Browser;
class PageNavigator;
class PrefService;
-class Browser;
namespace {
-class BookmarkNodeMenuController;
-// See description in declaration at bookmark_bar_view.cc.
-class ModelChangedListener;
class MenuRunner;
class ButtonSeparatorView;
struct DropInfo;
@@ -73,11 +70,31 @@ class BookmarkBarView : public ChromeViews::View,
public ChromeViews::ContextMenuController,
public ChromeViews::DragController,
public AnimationDelegate {
- friend class BookmarkNodeMenuController;
friend class MenuRunner;
friend class ShowFolderMenuTask;
public:
+ // Interface implemented by controllers/views that need to be notified any
+ // time the model changes, typically to cancel an operation that is showing
+ // data from the model such as a menu. This isn't intended as a general
+ // way to be notified of changes, rather for cases where a controller/view is
+ // showing data from the model in a modal like setting and needs to cleanly
+ // exit the modal loop if the model changes out from under it.
+ //
+ // A controller/view that needs this notification should install itself as the
+ // ModelChangeListener via the SetModelChangedListener method when shown and
+ // reset the ModelChangeListener of the BookmarkBarView when it closes by way
+ // of either the SetModelChangedListener method or the
+ // ClearModelChangedListenerIfEquals method.
+ class ModelChangedListener {
+ public:
+ virtual ~ModelChangedListener() {}
+
+ // Invoked when the model changes. Should cancel the edit and close any
+ // dialogs.
+ virtual void ModelChanged() = 0;
+ };
+
explicit BookmarkBarView(Profile* profile, Browser* browser);
virtual ~BookmarkBarView();
@@ -443,7 +460,7 @@ class BookmarkBarView : public ChromeViews::View,
// overflow_button_ or a button on the bar.
ChromeViews::BaseButton* throbbing_view_;
- DISALLOW_EVIL_CONSTRUCTORS(BookmarkBarView);
+ DISALLOW_COPY_AND_ASSIGN(BookmarkBarView);
};
-#endif // CHROME_BROWSER_VIEWS_BOOKMARK_BAR_VIEW_H__
+#endif // CHROME_BROWSER_VIEWS_BOOKMARK_BAR_VIEW_H_
diff --git a/chrome/test/unit/unittests.vcproj b/chrome/test/unit/unittests.vcproj
index b605e26..245996e 100644
--- a/chrome/test/unit/unittests.vcproj
+++ b/chrome/test/unit/unittests.vcproj
@@ -211,6 +211,14 @@
</File>
</Filter>
<Filter
+ Name="TestBookmarkBarContextMenuController"
+ >
+ <File
+ RelativePath="..\..\browser\bookmark_bar_context_menu_controller_test.cc"
+ >
+ </File>
+ </Filter>
+ <Filter
Name="TestBookmarkBarView"
>
<File