summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorben@chromium.org <ben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-03-19 22:22:56 +0000
committerben@chromium.org <ben@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-03-19 22:22:56 +0000
commit27239fb2b868ef6aff2d9d13932ba5debe87e9c7 (patch)
tree709dc5559aa96f57875ee48f449f86b5a0ae36eb
parenta5d16da421fc2eaa785204a9cf99e0c82ff159c4 (diff)
downloadchromium_src-27239fb2b868ef6aff2d9d13932ba5debe87e9c7.zip
chromium_src-27239fb2b868ef6aff2d9d13932ba5debe87e9c7.tar.gz
chromium_src-27239fb2b868ef6aff2d9d13932ba5debe87e9c7.tar.bz2
Allow dynamic switching in and out of sidetabs mode.
BUG=none TEST=none Review URL: http://codereview.chromium.org/1001003 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@42156 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/app/generated_resources.grd3
-rw-r--r--chrome/browser/browser.cc12
-rw-r--r--chrome/browser/browser.h5
-rw-r--r--chrome/browser/browser_window.h3
-rw-r--r--chrome/browser/cocoa/browser_window_cocoa.h1
-rw-r--r--chrome/browser/cocoa/browser_window_cocoa.mm4
-rw-r--r--chrome/browser/gtk/browser_window_gtk.cc4
-rw-r--r--chrome/browser/gtk/browser_window_gtk.h1
-rw-r--r--chrome/browser/tab_menu_model.cc5
-rw-r--r--chrome/browser/tabs/tab_strip_model.cc24
-rw-r--r--chrome/browser/tabs/tab_strip_model.h11
-rw-r--r--chrome/browser/views/frame/browser_frame.h8
-rw-r--r--chrome/browser/views/frame/browser_frame_gtk.cc6
-rw-r--r--chrome/browser/views/frame/browser_frame_gtk.h2
-rw-r--r--chrome/browser/views/frame/browser_frame_win.cc15
-rw-r--r--chrome/browser/views/frame/browser_frame_win.h2
-rw-r--r--chrome/browser/views/frame/browser_view.cc43
-rw-r--r--chrome/browser/views/frame/browser_view.h10
-rw-r--r--chrome/browser/views/frame/browser_view_layout.cc6
-rw-r--r--chrome/browser/views/frame/glass_browser_frame_view.cc11
-rw-r--r--chrome/browser/views/tabs/browser_tab_strip_controller.cc102
-rw-r--r--chrome/browser/views/tabs/browser_tab_strip_controller.h17
-rw-r--r--chrome/browser/views/tabs/side_tab.cc26
-rw-r--r--chrome/browser/views/tabs/side_tab.h9
-rw-r--r--chrome/browser/views/tabs/side_tab_strip.cc10
-rw-r--r--chrome/browser/views/tabs/side_tab_strip.h5
-rw-r--r--chrome/browser/views/tabs/side_tab_strip_model.h9
-rw-r--r--chrome/browser/views/tabs/tab.cc6
-rw-r--r--chrome/browser/views/tabs/tab.h4
-rw-r--r--chrome/browser/views/tabs/tab_strip.cc24
-rw-r--r--chrome/browser/views/tabs/tab_strip.h7
-rw-r--r--chrome/test/test_browser_window.h1
32 files changed, 337 insertions, 59 deletions
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index 02486fd..7d81442 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -4344,6 +4344,9 @@ Keep your key file in a safe place. You will need it to create new versions of y
<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>
+ <message name="IDS_TAB_CXMENU_USE_VERTICAL_TABS" desc="Use the vertical tab strip">
+ Use side 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.">
diff --git a/chrome/browser/browser.cc b/chrome/browser/browser.cc
index 378d86e..42e0834 100644
--- a/chrome/browser/browser.cc
+++ b/chrome/browser/browser.cc
@@ -190,6 +190,7 @@ Browser::Browser(Type type, Profile* profile)
encoding_auto_detect_.Init(prefs::kWebKitUsesUniversalDetector,
profile_->GetPrefs(), NULL);
+ use_vertical_tabs_.Init(prefs::kUseVerticalTabs, profile_->GetPrefs(), this);
}
Browser::~Browser() {
@@ -1566,7 +1567,7 @@ void Browser::RegisterUserPrefs(PrefService* prefs) {
prefs->RegisterBooleanPref(prefs::kWebAppCreateOnDesktop, true);
prefs->RegisterBooleanPref(prefs::kWebAppCreateInAppsMenu, true);
prefs->RegisterBooleanPref(prefs::kWebAppCreateInQuickLaunchBar, true);
- prefs->RegisterBooleanPref(prefs::kUseVerticalTabs, true);
+ prefs->RegisterBooleanPref(prefs::kUseVerticalTabs, false);
prefs->RegisterBooleanPref(prefs::kEnableTranslate, true);
}
@@ -1994,6 +1995,15 @@ void Browser::BookmarkAllTabs() {
BookmarkEditor::SHOW_TREE, NULL);
}
+bool Browser::UseVerticalTabs() const {
+ return use_vertical_tabs_.GetValue();
+}
+
+void Browser::ToggleUseVerticalTabs() {
+ use_vertical_tabs_.SetValue(!UseVerticalTabs());
+ window()->ToggleTabStripMode();
+}
+
///////////////////////////////////////////////////////////////////////////////
// Browser, TabStripModelObserver implementation:
diff --git a/chrome/browser/browser.h b/chrome/browser/browser.h
index 51470f7..e98966f 100644
--- a/chrome/browser/browser.h
+++ b/chrome/browser/browser.h
@@ -604,6 +604,8 @@ class Browser : public TabStripModelDelegate,
virtual bool CanCloseContentsAt(int index);
virtual bool CanBookmarkAllTabs() const;
virtual void BookmarkAllTabs();
+ virtual bool UseVerticalTabs() const;
+ virtual void ToggleUseVerticalTabs();
// Overridden from TabStripModelObserver:
virtual void TabInsertedAt(TabContents* contents,
@@ -944,6 +946,9 @@ class Browser : public TabStripModelDelegate,
// from a TabContents. Currently, only one pending action is allowed.
WebAppAction pending_web_app_action_;
+ // Tracks the display mode of the tabstrip.
+ mutable BooleanPrefMember use_vertical_tabs_;
+
DISALLOW_COPY_AND_ASSIGN(Browser);
};
diff --git a/chrome/browser/browser_window.h b/chrome/browser/browser_window.h
index a4ff572..1d3501a 100644
--- a/chrome/browser/browser_window.h
+++ b/chrome/browser/browser_window.h
@@ -310,6 +310,9 @@ class BrowserWindow {
virtual void Copy() = 0;
virtual void Paste() = 0;
+ // Switches between available tabstrip display modes.
+ virtual void ToggleTabStripMode() = 0;
+
// Construct a BrowserWindow implementation for the specified |browser|.
static BrowserWindow* CreateBrowserWindow(Browser* browser);
diff --git a/chrome/browser/cocoa/browser_window_cocoa.h b/chrome/browser/cocoa/browser_window_cocoa.h
index b0ace80..86a5e57 100644
--- a/chrome/browser/cocoa/browser_window_cocoa.h
+++ b/chrome/browser/cocoa/browser_window_cocoa.h
@@ -102,6 +102,7 @@ class BrowserWindowCocoa : public BrowserWindow,
virtual void Cut();
virtual void Copy();
virtual void Paste();
+ virtual void ToggleTabStripMode();
// Overridden from NotificationObserver
virtual void Observe(NotificationType type,
diff --git a/chrome/browser/cocoa/browser_window_cocoa.mm b/chrome/browser/cocoa/browser_window_cocoa.mm
index 01d592e..e9d0a31 100644
--- a/chrome/browser/cocoa/browser_window_cocoa.mm
+++ b/chrome/browser/cocoa/browser_window_cocoa.mm
@@ -540,6 +540,10 @@ void BrowserWindowCocoa::Paste() {
[NSApp sendAction:@selector(paste:) to:nil from:nil];
}
+void BrowserWindowCocoa::ToggleTabStripMode() {
+ NOTIMPLEMENTED();
+}
+
void BrowserWindowCocoa::Observe(NotificationType type,
const NotificationSource& source,
const NotificationDetails& details) {
diff --git a/chrome/browser/gtk/browser_window_gtk.cc b/chrome/browser/gtk/browser_window_gtk.cc
index 873ad44..e79da68 100644
--- a/chrome/browser/gtk/browser_window_gtk.cc
+++ b/chrome/browser/gtk/browser_window_gtk.cc
@@ -1044,6 +1044,10 @@ void BrowserWindowGtk::Paste() {
DoCutCopyPaste(this, &RenderViewHost::Paste, "paste-clipboard");
}
+void BrowserWindowGtk::ToggleTabStripMode() {
+ NOTIMPLEMENTED();
+}
+
void BrowserWindowGtk::ConfirmBrowserCloseWithPendingDownloads() {
new DownloadInProgressDialogGtk(browser());
}
diff --git a/chrome/browser/gtk/browser_window_gtk.h b/chrome/browser/gtk/browser_window_gtk.h
index f24e094..db1aba2 100644
--- a/chrome/browser/gtk/browser_window_gtk.h
+++ b/chrome/browser/gtk/browser_window_gtk.h
@@ -120,6 +120,7 @@ class BrowserWindowGtk : public BrowserWindow,
virtual void Cut();
virtual void Copy();
virtual void Paste();
+ virtual void ToggleTabStripMode();
// Overridden from NotificationObserver:
virtual void Observe(NotificationType type,
diff --git a/chrome/browser/tab_menu_model.cc b/chrome/browser/tab_menu_model.cc
index f0fe251..2845240 100644
--- a/chrome/browser/tab_menu_model.cc
+++ b/chrome/browser/tab_menu_model.cc
@@ -43,4 +43,9 @@ void TabMenuModel::Build() {
AddItemWithStringId(TabStripModel::CommandRestoreTab, IDS_RESTORE_TAB);
AddItemWithStringId(TabStripModel::CommandBookmarkAllTabs,
IDS_TAB_CXMENU_BOOKMARK_ALL_TABS);
+#if defined(OS_WIN)
+ AddSeparator();
+ AddCheckItemWithStringId(TabStripModel::CommandUseVerticalTabs,
+ IDS_TAB_CXMENU_USE_VERTICAL_TABS);
+#endif
}
diff --git a/chrome/browser/tabs/tab_strip_model.cc b/chrome/browser/tabs/tab_strip_model.cc
index 2fba4b5..dc9b968 100644
--- a/chrome/browser/tabs/tab_strip_model.cc
+++ b/chrome/browser/tabs/tab_strip_model.cc
@@ -574,11 +574,25 @@ bool TabStripModel::IsContextMenuCommandEnabled(
return delegate_->CanRestoreTab();
case CommandTogglePinned:
return true;
- case CommandBookmarkAllTabs: {
+ case CommandBookmarkAllTabs:
return delegate_->CanBookmarkAllTabs();
- }
+ case CommandUseVerticalTabs:
+ return true;
+ default:
+ NOTREACHED();
+ }
+ return false;
+}
+
+bool TabStripModel::IsContextMenuCommandChecked(
+ int context_index,
+ ContextMenuCommand command_id) const {
+ switch (command_id) {
+ case CommandUseVerticalTabs:
+ return delegate()->UseVerticalTabs();
default:
NOTREACHED();
+ break;
}
return false;
}
@@ -656,6 +670,12 @@ void TabStripModel::ExecuteContextMenuCommand(
delegate_->BookmarkAllTabs();
break;
}
+ case CommandUseVerticalTabs: {
+ UserMetrics::RecordAction("TabContextMenu_UseVerticalTabs", profile_);
+
+ delegate()->ToggleUseVerticalTabs();
+ break;
+ }
default:
NOTREACHED();
}
diff --git a/chrome/browser/tabs/tab_strip_model.h b/chrome/browser/tabs/tab_strip_model.h
index a4c3641..1f5214f 100644
--- a/chrome/browser/tabs/tab_strip_model.h
+++ b/chrome/browser/tabs/tab_strip_model.h
@@ -223,6 +223,12 @@ class TabStripModelDelegate {
// Creates a bookmark folder containing a bookmark for all open tabs.
virtual void BookmarkAllTabs() = 0;
+
+ // Returns true if the vertical tabstrip presentation should be used.
+ virtual bool UseVerticalTabs() const = 0;
+
+ // Toggles the use of the vertical tabstrip.
+ virtual void ToggleUseVerticalTabs() = 0;
};
////////////////////////////////////////////////////////////////////////////////
@@ -547,6 +553,7 @@ class TabStripModel : public NotificationObserver {
CommandRestoreTab,
CommandTogglePinned,
CommandBookmarkAllTabs,
+ CommandUseVerticalTabs,
CommandLast
};
@@ -554,6 +561,10 @@ class TabStripModel : public NotificationObserver {
bool IsContextMenuCommandEnabled(int context_index,
ContextMenuCommand command_id) const;
+ // Returns true if the specified command is checked.
+ bool IsContextMenuCommandChecked(int context_index,
+ ContextMenuCommand command_id) const;
+
// Performs the action associated with the specified command for the given
// TabStripModel index |context_index|.
void ExecuteContextMenuCommand(int context_index,
diff --git a/chrome/browser/views/frame/browser_frame.h b/chrome/browser/views/frame/browser_frame.h
index fd94d51..392200d 100644
--- a/chrome/browser/views/frame/browser_frame.h
+++ b/chrome/browser/views/frame/browser_frame.h
@@ -41,10 +41,6 @@ class BrowserFrame {
// construction.
virtual views::Window* GetWindow() = 0;
- // Notification that the tab strip has been created. This should let the
- // BrowserRootView know about it so it can enable drag and drop.
- virtual void TabStripCreated(BaseTabStrip* tabstrip) = 0;
-
// Determine the distance of the left edge of the minimize button from the
// left edge of the window. Used in our Non-Client View's Layout.
virtual int GetMinimizeButtonOffset() const = 0;
@@ -74,6 +70,10 @@ class BrowserFrame {
// calls this method _after_ the TabStrip has painted itself so the shadow is
// rendered above the tabs.
virtual void PaintTabStripShadow(gfx::Canvas* canvas) = 0;
+
+ // Notifies the frame that the tab strip display mode changed so it can update
+ // its frame treatment if necessary.
+ virtual void TabStripDisplayModeChanged() = 0;
};
#endif // CHROME_BROWSER_VIEWS_FRAME_BROWSER_FRAME_H_
diff --git a/chrome/browser/views/frame/browser_frame_gtk.cc b/chrome/browser/views/frame/browser_frame_gtk.cc
index 9e1699c..97fbedc 100644
--- a/chrome/browser/views/frame/browser_frame_gtk.cc
+++ b/chrome/browser/views/frame/browser_frame_gtk.cc
@@ -102,9 +102,6 @@ views::Window* BrowserFrameGtk::GetWindow() {
return this;
}
-void BrowserFrameGtk::TabStripCreated(BaseTabStrip* tabstrip) {
-}
-
int BrowserFrameGtk::GetMinimizeButtonOffset() const {
NOTIMPLEMENTED();
return 0;
@@ -139,6 +136,9 @@ views::View* BrowserFrameGtk::GetFrameView() const {
void BrowserFrameGtk::PaintTabStripShadow(gfx::Canvas* canvas) {
}
+void BrowserFrameGtk::TabStripDisplayModeChanged() {
+}
+
ThemeProvider* BrowserFrameGtk::GetThemeProvider() const {
return profile_->GetThemeProvider();
}
diff --git a/chrome/browser/views/frame/browser_frame_gtk.h b/chrome/browser/views/frame/browser_frame_gtk.h
index 93330c1..f8e8f2a 100644
--- a/chrome/browser/views/frame/browser_frame_gtk.h
+++ b/chrome/browser/views/frame/browser_frame_gtk.h
@@ -28,7 +28,6 @@ class BrowserFrameGtk : public BrowserFrame,
// Overridden from BrowserFrame:
virtual views::Window* GetWindow();
- virtual void TabStripCreated(BaseTabStrip* tabstrip);
virtual int GetMinimizeButtonOffset() const;
virtual gfx::Rect GetBoundsForTabStrip(BaseTabStrip* tabstrip) const;
virtual void UpdateThrobber(bool running);
@@ -37,6 +36,7 @@ class BrowserFrameGtk : public BrowserFrame,
virtual bool AlwaysUseNativeFrame() const;
virtual views::View* GetFrameView() const;
virtual void PaintTabStripShadow(gfx::Canvas* canvas);
+ virtual void TabStripDisplayModeChanged();
// Overridden from views::Widget:
virtual ThemeProvider* GetThemeProvider() const;
diff --git a/chrome/browser/views/frame/browser_frame_win.cc b/chrome/browser/views/frame/browser_frame_win.cc
index 696e109..4578829 100644
--- a/chrome/browser/views/frame/browser_frame_win.cc
+++ b/chrome/browser/views/frame/browser_frame_win.cc
@@ -69,9 +69,6 @@ views::Window* BrowserFrameWin::GetWindow() {
return this;
}
-void BrowserFrameWin::TabStripCreated(BaseTabStrip* tabstrip) {
-}
-
int BrowserFrameWin::GetMinimizeButtonOffset() const {
TITLEBARINFOEX titlebar_info;
titlebar_info.cbSize = sizeof(TITLEBARINFOEX);
@@ -127,6 +124,14 @@ void BrowserFrameWin::PaintTabStripShadow(gfx::Canvas* canvas) {
browser_frame_view_->PaintTabStripShadow(canvas);
}
+void BrowserFrameWin::TabStripDisplayModeChanged() {
+ UpdateDWMFrame();
+ // We need to relayout only after the window frame has had a chance to update
+ // the size/position of its controls (e.g. minimize/maximize/close) so that
+ // the tabstrip can layout at its correct bounds.
+ GetRootView()->Layout();
+}
+
///////////////////////////////////////////////////////////////////////////////
// BrowserFrame, views::WindowWin overrides:
@@ -294,7 +299,7 @@ void BrowserFrameWin::UpdateDWMFrame() {
// In maximized mode, we only have a titlebar strip of glass, no side/bottom
// borders.
if (!browser_view_->IsFullscreen()) {
- if (browser_view_->UsingSideTabs()) {
+ if (browser_view_->UseVerticalTabs()) {
margins.cxLeftWidth +=
GetBoundsForTabStrip(browser_view_->tabstrip()).right();
margins.cyTopHeight += GetSystemMetrics(SM_CYSIZEFRAME);
@@ -309,7 +314,7 @@ void BrowserFrameWin::UpdateDWMFrame() {
DwmExtendFrameIntoClientArea(GetNativeView(), &margins);
DWORD window_style = GetWindowLong(GWL_STYLE);
- if (browser_view_->UsingSideTabs()) {
+ if (browser_view_->UseVerticalTabs()) {
if (window_style & WS_CAPTION)
SetWindowLong(GWL_STYLE, window_style & ~WS_CAPTION);
} else {
diff --git a/chrome/browser/views/frame/browser_frame_win.h b/chrome/browser/views/frame/browser_frame_win.h
index d928f93..42e8974 100644
--- a/chrome/browser/views/frame/browser_frame_win.h
+++ b/chrome/browser/views/frame/browser_frame_win.h
@@ -37,7 +37,6 @@ class BrowserFrameWin : public BrowserFrame, public views::WindowWin {
// BrowserFrame implementation.
virtual views::Window* GetWindow();
- virtual void TabStripCreated(BaseTabStrip* tabstrip);
virtual int GetMinimizeButtonOffset() const;
virtual gfx::Rect GetBoundsForTabStrip(BaseTabStrip* tabstrip) const;
virtual void UpdateThrobber(bool running);
@@ -46,6 +45,7 @@ class BrowserFrameWin : public BrowserFrame, public views::WindowWin {
virtual bool AlwaysUseNativeFrame() const;
virtual views::View* GetFrameView() const;
virtual void PaintTabStripShadow(gfx::Canvas* canvas);
+ virtual void TabStripDisplayModeChanged();
protected:
// Overridden from views::WindowWin:
diff --git a/chrome/browser/views/frame/browser_view.cc b/chrome/browser/views/frame/browser_view.cc
index 3312812..f8e4da4 100644
--- a/chrome/browser/views/frame/browser_view.cc
+++ b/chrome/browser/views/frame/browser_view.cc
@@ -544,8 +544,8 @@ bool BrowserView::IsTabStripVisible() const {
return browser_->SupportsWindowFeature(Browser::FEATURE_TABSTRIP);
}
-bool BrowserView::UsingSideTabs() const {
- return SideTabStrip::Visible(browser_->profile());
+bool BrowserView::UseVerticalTabs() const {
+ return browser_->tabstrip_model()->delegate()->UseVerticalTabs();
}
bool BrowserView::IsOffTheRecord() const {
@@ -1224,6 +1224,11 @@ void BrowserView::Paste() {
false, false);
}
+void BrowserView::ToggleTabStripMode() {
+ InitTabStrip(browser_->tabstrip_model());
+ frame_->TabStripDisplayModeChanged();
+}
+
///////////////////////////////////////////////////////////////////////////////
// BrowserView, BrowserWindowTesting implementation:
@@ -1641,13 +1646,32 @@ views::LayoutManager* BrowserView::CreateLayoutManager() const {
return new BrowserViewLayout;
}
-BaseTabStrip* BrowserView::CreateTabStrip(TabStripModel* model) {
- if (UsingSideTabs()) {
+void BrowserView::InitTabStrip(TabStripModel* model) {
+// Throw away the existing tabstrip if we're switching display modes.
+ if (tabstrip_) {
+ tabstrip_->GetParent()->RemoveChildView(tabstrip_);
+ delete tabstrip_;
+ }
+
+ TabStrip* tabstrip_as_tabstrip = NULL;
+ BrowserTabStripController* tabstrip_controller = NULL;
+
+ if (UseVerticalTabs()) {
SideTabStrip* tabstrip = new SideTabStrip;
- tabstrip->SetModel(new BrowserTabStripController(model, tabstrip));
- return tabstrip;
+ tabstrip_controller = new BrowserTabStripController(model, tabstrip);
+ tabstrip->SetModel(tabstrip_controller);
+ tabstrip_ = tabstrip;
+ } else {
+ tabstrip_as_tabstrip = new TabStrip(model);
+ tabstrip_ = tabstrip_as_tabstrip;
}
- return new TabStrip(model);
+ tabstrip_->SetAccessibleName(l10n_util::GetString(IDS_ACCNAME_TABSTRIP));
+ AddChildView(tabstrip_);
+
+ if (tabstrip_controller)
+ tabstrip_controller->InitFromModel();
+ else
+ tabstrip_as_tabstrip->InitFromModel();
}
///////////////////////////////////////////////////////////////////////////////
@@ -1674,10 +1698,7 @@ void BrowserView::Init() {
LoadAccelerators();
SetAccessibleName(l10n_util::GetString(IDS_PRODUCT_NAME));
- tabstrip_ = CreateTabStrip(browser_->tabstrip_model());
- tabstrip_->SetAccessibleName(l10n_util::GetString(IDS_ACCNAME_TABSTRIP));
- AddChildView(tabstrip_);
- frame_->TabStripCreated(tabstrip_);
+ InitTabStrip(browser_->tabstrip_model());
toolbar_ = new ToolbarView(browser_.get());
AddChildView(toolbar_);
diff --git a/chrome/browser/views/frame/browser_view.h b/chrome/browser/views/frame/browser_view.h
index bf753e9..5452bc8 100644
--- a/chrome/browser/views/frame/browser_view.h
+++ b/chrome/browser/views/frame/browser_view.h
@@ -151,7 +151,7 @@ class BrowserView : public BrowserBubbleHost,
bool IsTabStripVisible() const;
// Returns true if the vertical tabstrip is in use.
- bool UsingSideTabs() const;
+ bool UseVerticalTabs() const;
// Returns true if the profile associated with this Browser window is
// off the record.
@@ -322,6 +322,7 @@ class BrowserView : public BrowserBubbleHost,
virtual void Cut();
virtual void Copy();
virtual void Paste();
+ virtual void ToggleTabStripMode();
// Overridden from BrowserWindowTesting:
virtual BookmarkBarView* GetBookmarkBarView() const;
@@ -397,9 +398,10 @@ class BrowserView : public BrowserBubbleHost,
// override to implemnet different layout pocily.
virtual views::LayoutManager* CreateLayoutManager() const;
- // Returns a new TabStrip for the browser view. A subclass may
- // override to return a different TabStrip implementation.
- virtual BaseTabStrip* CreateTabStrip(TabStripModel* tab_strip_model);
+ // Initializes a new TabStrip for the browser view. This can be performed
+ // multiple times over the life of the browser, and is run when the display
+ // mode for the tabstrip changes from horizontal to vertical.
+ void InitTabStrip(TabStripModel* tab_strip_model);
// Browser window related initializations.
virtual void Init();
diff --git a/chrome/browser/views/frame/browser_view_layout.cc b/chrome/browser/views/frame/browser_view_layout.cc
index 2c11574..e632534 100644
--- a/chrome/browser/views/frame/browser_view_layout.cc
+++ b/chrome/browser/views/frame/browser_view_layout.cc
@@ -285,7 +285,7 @@ int BrowserViewLayout::LayoutTabStrip() {
gfx::Rect layout_bounds =
browser_view_->frame()->GetBoundsForTabStrip(tabstrip_);
- if (browser_view_->UsingSideTabs()) {
+ if (browser_view_->UseVerticalTabs()) {
vertical_layout_rect_.Inset(
layout_bounds.right() - kBrowserViewTabStripHorizontalOverlap, 0, 0, 0);
} else {
@@ -301,7 +301,7 @@ int BrowserViewLayout::LayoutTabStrip() {
layout_bounds.set_origin(tabstrip_origin);
tabstrip_->SetVisible(true);
tabstrip_->SetBounds(layout_bounds);
- return browser_view_->UsingSideTabs() ? 0 : layout_bounds.bottom();
+ return browser_view_->UseVerticalTabs() ? 0 : layout_bounds.bottom();
}
int BrowserViewLayout::LayoutToolbar(int top) {
@@ -309,7 +309,7 @@ int BrowserViewLayout::LayoutToolbar(int top) {
bool visible = browser_view_->IsToolbarVisible();
toolbar_->location_bar()->SetFocusable(visible);
int y = 0;
- if (!browser_view_->UsingSideTabs()) {
+ if (!browser_view_->UseVerticalTabs()) {
y = top -
((visible && browser_view_->IsTabStripVisible())
? kToolbarTabStripVerticalOverlap : 0);
diff --git a/chrome/browser/views/frame/glass_browser_frame_view.cc b/chrome/browser/views/frame/glass_browser_frame_view.cc
index 04c2bd6..f62d063 100644
--- a/chrome/browser/views/frame/glass_browser_frame_view.cc
+++ b/chrome/browser/views/frame/glass_browser_frame_view.cc
@@ -83,7 +83,7 @@ GlassBrowserFrameView::~GlassBrowserFrameView() {
gfx::Rect GlassBrowserFrameView::GetBoundsForTabStrip(
BaseTabStrip* tabstrip) const {
- if (browser_view_->UsingSideTabs()) {
+ if (browser_view_->UseVerticalTabs()) {
gfx::Size ps = tabstrip->GetPreferredSize();
return gfx::Rect(0, NonClientTopBorderHeight(), ps.width(),
browser_view_->height());
@@ -120,6 +120,9 @@ void GlassBrowserFrameView::UpdateThrobber(bool running) {
}
void GlassBrowserFrameView::PaintTabStripShadow(gfx::Canvas* canvas) {
+ if (!browser_view_->UseVerticalTabs())
+ return;
+
ThemeProvider* tp = GetThemeProvider();
SkBitmap* shadow_top = tp->GetBitmapNamed(IDR_SIDETABS_SHADOW_TOP);
SkBitmap* shadow_middle = tp->GetBitmapNamed(IDR_SIDETABS_SHADOW_MIDDLE);
@@ -242,7 +245,7 @@ int GlassBrowserFrameView::NonClientTopBorderHeight() const {
// We'd like to use FrameBorderThickness() here, but the maximized Aero glass
// frame has a 0 frame border around most edges and a CXSIZEFRAME-thick border
// at the top (see AeroGlassFrame::OnGetMinMaxInfo()).
- const int kRestoredHeight = browser_view_->UsingSideTabs() ?
+ const int kRestoredHeight = browser_view_->UseVerticalTabs() ?
-2 : kNonClientRestoredExtraThickness;
return GetSystemMetrics(SM_CXSIZEFRAME) + (browser_view_->IsMaximized() ?
-kTabstripTopShadowThickness : kRestoredHeight);
@@ -274,7 +277,7 @@ void GlassBrowserFrameView::PaintToolbarBackground(gfx::Canvas* canvas) {
// Draw the toolbar background, setting src_y of the paint to the tab
// strip height as the toolbar background begins at the top of the tabs.
- int src_y = browser_view_->UsingSideTabs()
+ int src_y = browser_view_->UseVerticalTabs()
? TabRenderer::GetMinimumUnselectedSize().height()
: browser_view_->GetTabStripHeight() - 1;
canvas->TileImageInt(*theme_toolbar, 0, src_y,
@@ -324,7 +327,7 @@ void GlassBrowserFrameView::PaintRestoredClientEdge(gfx::Canvas* canvas) {
tp->GetBitmapNamed(IDR_CONTENT_TOP_LEFT_CORNER)->height();
gfx::Rect client_area_bounds = CalculateClientAreaBounds(width(), height());
- if (browser_view_->UsingSideTabs()) {
+ if (browser_view_->UseVerticalTabs()) {
client_area_bounds.Inset(
GetBoundsForTabStrip(browser_view_->tabstrip()).width() - 4, 0, 0, 0);
}
diff --git a/chrome/browser/views/tabs/browser_tab_strip_controller.cc b/chrome/browser/views/tabs/browser_tab_strip_controller.cc
index 343ee09..da30f47 100644
--- a/chrome/browser/views/tabs/browser_tab_strip_controller.cc
+++ b/chrome/browser/views/tabs/browser_tab_strip_controller.cc
@@ -5,7 +5,68 @@
#include "chrome/browser/views/tabs/browser_tab_strip_controller.h"
#include "chrome/browser/tab_contents/tab_contents.h"
+#include "chrome/browser/tab_menu_model.h"
#include "chrome/browser/views/tabs/side_tab_strip.h"
+#include "views/controls/menu/menu_2.h"
+#include "views/widget/widget.h"
+
+class BrowserTabStripController::TabContextMenuContents
+ : public menus::SimpleMenuModel::Delegate {
+ public:
+ TabContextMenuContents(int tab_index, BrowserTabStripController* controller)
+ : ALLOW_THIS_IN_INITIALIZER_LIST(model_(this)),
+ tab_index_(tab_index),
+ controller_(controller) {
+ Build();
+ }
+ virtual ~TabContextMenuContents() {
+ menu_->CancelMenu();
+ }
+
+ void RunMenuAt(const gfx::Point& point) {
+ menu_->RunMenuAt(point, views::Menu2::ALIGN_TOPLEFT);
+ }
+
+ // Overridden from menus::SimpleMenuModel::Delegate:
+ virtual bool IsCommandIdChecked(int command_id) const {
+ return controller_->IsCommandCheckedForTab(
+ static_cast<TabStripModel::ContextMenuCommand>(command_id),
+ tab_index_);
+ }
+ virtual bool IsCommandIdEnabled(int command_id) const {
+ return controller_->IsCommandEnabledForTab(
+ static_cast<TabStripModel::ContextMenuCommand>(command_id),
+ tab_index_);
+ }
+ virtual bool GetAcceleratorForCommandId(
+ int command_id,
+ menus::Accelerator* accelerator) {
+ return controller_->tabstrip_->GetWidget()->GetAccelerator(command_id,
+ accelerator);
+ }
+ virtual void ExecuteCommand(int command_id) {
+ controller_->ExecuteCommandForTab(
+ static_cast<TabStripModel::ContextMenuCommand>(command_id),
+ tab_index_);
+ }
+
+ private:
+ void Build() {
+ menu_.reset(new views::Menu2(&model_));
+ }
+
+ TabMenuModel model_;
+ scoped_ptr<views::Menu2> menu_;
+
+ // The index of the tab we are showing the context menu for.
+ int tab_index_;
+
+ // A pointer back to our hosting controller, for command state information.
+ BrowserTabStripController* controller_;
+
+ DISALLOW_COPY_AND_ASSIGN(TabContextMenuContents);
+};
+
////////////////////////////////////////////////////////////////////////////////
// BrowserTabStripController, public:
@@ -18,6 +79,40 @@ BrowserTabStripController::BrowserTabStripController(TabStripModel* model,
}
BrowserTabStripController::~BrowserTabStripController() {
+ model_->RemoveObserver(this);
+}
+
+void BrowserTabStripController::InitFromModel() {
+ // Walk the model, calling our insertion observer method for each item within
+ // it.
+ for (int i = 0; i < model_->count(); ++i) {
+ TabInsertedAt(model_->GetTabContentsAt(i), i,
+ i == model_->selected_index());
+ }
+}
+
+bool BrowserTabStripController::IsCommandEnabledForTab(
+ TabStripModel::ContextMenuCommand command_id, int tab_index) const {
+ if (model_->ContainsIndex(tab_index))
+ return model_->IsContextMenuCommandEnabled(tab_index, command_id);
+ return false;
+}
+
+bool BrowserTabStripController::IsCommandCheckedForTab(
+ TabStripModel::ContextMenuCommand command_id, int tab_index) const {
+ // TODO(beng): move to TabStripModel, see note in IsTabPinned.
+ if (command_id == TabStripModel::CommandTogglePinned)
+ return false;
+
+ if (model_->ContainsIndex(tab_index))
+ return model_->IsContextMenuCommandChecked(tab_index, command_id);
+ return false;
+}
+
+void BrowserTabStripController::ExecuteCommandForTab(
+ TabStripModel::ContextMenuCommand command_id, int tab_index) {
+ if (model_->ContainsIndex(tab_index))
+ model_->ExecuteContextMenuCommand(tab_index, command_id);
}
////////////////////////////////////////////////////////////////////////////////
@@ -53,6 +148,13 @@ void BrowserTabStripController::CloseTab(int index) {
model_->CloseTabContentsAt(index);
}
+void BrowserTabStripController::ShowContextMenu(int index,
+ const gfx::Point& p) {
+ if (!context_menu_contents_.get())
+ context_menu_contents_.reset(new TabContextMenuContents(index, this));
+ context_menu_contents_->RunMenuAt(p);
+}
+
////////////////////////////////////////////////////////////////////////////////
// BrowserTabStripController, TabStripModelObserver implementation:
diff --git a/chrome/browser/views/tabs/browser_tab_strip_controller.h b/chrome/browser/views/tabs/browser_tab_strip_controller.h
index e127659..c50fcdb 100644
--- a/chrome/browser/views/tabs/browser_tab_strip_controller.h
+++ b/chrome/browser/views/tabs/browser_tab_strip_controller.h
@@ -5,6 +5,8 @@
#ifndef CHROME_BROWSER_VIEWS_TABS_BROWSER_TAB_STRIP_CONTROLLER_H_
#define CHROME_BROWSER_VIEWS_TABS_BROWSER_TAB_STRIP_CONTROLLER_H_
+#include "base/scoped_ptr.h"
+
#include "chrome/browser/tabs/tab_strip_model.h"
#include "chrome/browser/views/tabs/side_tab_strip_model.h"
@@ -18,6 +20,15 @@ class BrowserTabStripController : public SideTabStripModel,
BrowserTabStripController(TabStripModel* model, SideTabStrip* tabstrip);
virtual ~BrowserTabStripController();
+ void InitFromModel();
+
+ bool IsCommandEnabledForTab(TabStripModel::ContextMenuCommand command_id,
+ int tab_index) const;
+ bool IsCommandCheckedForTab(TabStripModel::ContextMenuCommand command_id,
+ int tab_index) const;
+ void ExecuteCommandForTab(TabStripModel::ContextMenuCommand command_id,
+ int tab_index);
+
// SideTabStripModel implementation:
virtual SkBitmap GetIcon(int index) const;
virtual string16 GetTitle(int index) const;
@@ -25,6 +36,7 @@ class BrowserTabStripController : public SideTabStripModel,
virtual NetworkState GetNetworkState(int index) const;
virtual void SelectTab(int index);
virtual void CloseTab(int index);
+ virtual void ShowContextMenu(int index, const gfx::Point& p);
// TabStripModelObserver implementation:
virtual void TabInsertedAt(TabContents* contents, int index,
@@ -43,9 +55,14 @@ class BrowserTabStripController : public SideTabStripModel,
virtual void TabBlockedStateChanged(TabContents* contents, int index);
private:
+ class TabContextMenuContents;
+
TabStripModel* model_;
SideTabStrip* tabstrip_;
+ // If non-NULL it means we're showing a menu for the tab.
+ scoped_ptr<TabContextMenuContents> context_menu_contents_;
+
DISALLOW_COPY_AND_ASSIGN(BrowserTabStripController);
};
diff --git a/chrome/browser/views/tabs/side_tab.cc b/chrome/browser/views/tabs/side_tab.cc
index c08eaaa..ee160d7 100644
--- a/chrome/browser/views/tabs/side_tab.cc
+++ b/chrome/browser/views/tabs/side_tab.cc
@@ -56,6 +56,8 @@ SideTab::SideTab(SideTabModel* model)
hover_animation_.reset(new SlideAnimation(this));
hover_animation_->SetSlideDuration(kHoverDurationMs);
+
+ SetContextMenuController(this);
}
SideTab::~SideTab() {
@@ -110,6 +112,15 @@ void SideTab::ButtonPressed(views::Button* sender, const views::Event& event) {
}
////////////////////////////////////////////////////////////////////////////////
+// SideTab, views::ContextMenuController implementation:
+
+void SideTab::ShowContextMenu(views::View* source,
+ const gfx::Point& p,
+ bool is_mouse_gesture) {
+ model_->ShowContextMenu(this, p);
+}
+
+////////////////////////////////////////////////////////////////////////////////
// SideTab, views::View overrides:
void SideTab::Layout() {
@@ -119,14 +130,19 @@ void SideTab::Layout() {
gfx::Size ps = close_button_->GetPreferredSize();
int close_y = (height() - ps.height()) / 2;
- close_button_->SetBounds(width() - ps.width() - close_y, close_y, ps.width(),
- ps.height());
+ close_button_->SetBounds(
+ std::max(0, width() - ps.width() - close_y),
+ close_y,
+ ps.width(),
+ ps.height());
int title_y = (height() - font_->height()) / 2;
int title_x = icon_bounds_.right() + kIconTitleSpacing;
- title_bounds_.SetRect(title_x, title_y,
- close_button_->x() - kTitleCloseSpacing - title_x,
- font_->height());
+ title_bounds_.SetRect(
+ title_x,
+ title_y,
+ std::max(0, close_button_->x() - kTitleCloseSpacing - title_x),
+ font_->height());
}
void SideTab::Paint(gfx::Canvas* canvas) {
diff --git a/chrome/browser/views/tabs/side_tab.h b/chrome/browser/views/tabs/side_tab.h
index 72fc8b0..59e568b 100644
--- a/chrome/browser/views/tabs/side_tab.h
+++ b/chrome/browser/views/tabs/side_tab.h
@@ -26,9 +26,13 @@ class SideTabModel {
// Closes the tab.
virtual void CloseTab(SideTab* tab) = 0;
+
+ // Shows a context menu for the tab at the specified point in screen coords.
+ virtual void ShowContextMenu(SideTab* tab, const gfx::Point& p) = 0;
};
class SideTab : public views::View,
+ public views::ContextMenuController,
public views::ButtonListener,
public AnimationDelegate {
public:
@@ -48,6 +52,11 @@ class SideTab : public views::View,
// views::ButtonListener implementation:
virtual void ButtonPressed(views::Button* sender, const views::Event& event);
+ // views::ContextMenuController implementation:
+ virtual void ShowContextMenu(views::View* source,
+ const gfx::Point& p,
+ bool is_mouse_gesture);
+
// views::View Overrides:
virtual void Layout();
virtual void Paint(gfx::Canvas* canvas);
diff --git a/chrome/browser/views/tabs/side_tab_strip.cc b/chrome/browser/views/tabs/side_tab_strip.cc
index 6896d42..6912f2c 100644
--- a/chrome/browser/views/tabs/side_tab_strip.cc
+++ b/chrome/browser/views/tabs/side_tab_strip.cc
@@ -38,12 +38,6 @@ bool SideTabStrip::Available() {
switches::kEnableVerticalTabs);
}
-// static
-bool SideTabStrip::Visible(Profile* profile) {
- return Available() &&
- profile->GetPrefs()->GetBoolean(prefs::kUseVerticalTabs);
-}
-
void SideTabStrip::AddTabAt(int index) {
SideTab* tab = new SideTab(this);
AddChildView(tab);
@@ -88,6 +82,10 @@ void SideTabStrip::CloseTab(SideTab* tab) {
model_->CloseTab(GetIndexOfSideTab(tab));
}
+void SideTabStrip::ShowContextMenu(SideTab* tab, const gfx::Point& p) {
+ model_->ShowContextMenu(GetIndexOfSideTab(tab), p);
+}
+
////////////////////////////////////////////////////////////////////////////////
// SideTabStrip, BaseTabStrip implementation:
diff --git a/chrome/browser/views/tabs/side_tab_strip.h b/chrome/browser/views/tabs/side_tab_strip.h
index 71b704a..b1716ba 100644
--- a/chrome/browser/views/tabs/side_tab_strip.h
+++ b/chrome/browser/views/tabs/side_tab_strip.h
@@ -25,10 +25,6 @@ class SideTabStrip : public BaseTabStrip,
// command line flag that allows the SideTabStrip to be optionally shown.
static bool Available();
- // Whether or not the vertical tabstrip is shown. Only valid if Available()
- // returns true.
- static bool Visible(Profile* profile);
-
// Notifies the SideTabStrip that a tab was added in the model at |index|.
void AddTabAt(int index);
@@ -48,6 +44,7 @@ class SideTabStrip : public BaseTabStrip,
virtual bool IsSelected(SideTab* tab) const;
virtual void SelectTab(SideTab* tab);
virtual void CloseTab(SideTab* tab);
+ virtual void ShowContextMenu(SideTab* tab, const gfx::Point& p);
// BaseTabStrip implementation:
virtual int GetPreferredHeight();
diff --git a/chrome/browser/views/tabs/side_tab_strip_model.h b/chrome/browser/views/tabs/side_tab_strip_model.h
index a456c36..835e5ba 100644
--- a/chrome/browser/views/tabs/side_tab_strip_model.h
+++ b/chrome/browser/views/tabs/side_tab_strip_model.h
@@ -7,12 +7,17 @@
#include "base/string16.h"
+namespace gfx {
+class Point;
+}
class SkBitmap;
// A model interface implemented by an object that can provide information
// about SideTabs in a SideTabStrip.
class SideTabStripModel {
public:
+ virtual ~SideTabStripModel() {}
+
// Returns metadata about the tab at the specified index.
virtual SkBitmap GetIcon(int index) const = 0;
virtual string16 GetTitle(int index) const = 0;
@@ -35,6 +40,10 @@ class SideTabStripModel {
// Closes the tab at the specified index in the model.
virtual void CloseTab(int index) = 0;
+
+ // Shows a context menu for the tab at the specified index at the specified
+ // point in screen coords.
+ virtual void ShowContextMenu(int index, const gfx::Point& p) = 0;
};
#endif // CHROME_BROWSER_VIEWS_TABS_SIDE_TAB_STRIP_MODEL_H_
diff --git a/chrome/browser/views/tabs/tab.cc b/chrome/browser/views/tabs/tab.cc
index 4c6aa46..275af42 100644
--- a/chrome/browser/views/tabs/tab.cc
+++ b/chrome/browser/views/tabs/tab.cc
@@ -51,9 +51,9 @@ class Tab::TabContextMenuContents : public menus::SimpleMenuModel::Delegate {
// Overridden from menus::SimpleMenuModel::Delegate:
virtual bool IsCommandIdChecked(int command_id) const {
- if (!tab_ || command_id != TabStripModel::CommandTogglePinned)
- return false;
- return tab_->delegate()->IsTabPinned(tab_);
+ return tab_ && tab_->delegate()->IsCommandCheckedForTab(
+ static_cast<TabStripModel::ContextMenuCommand>(command_id),
+ tab_);
}
virtual bool IsCommandIdEnabled(int command_id) const {
return tab_ && tab_->delegate()->IsCommandEnabledForTab(
diff --git a/chrome/browser/views/tabs/tab.h b/chrome/browser/views/tabs/tab.h
index f491291..6a9bf21 100644
--- a/chrome/browser/views/tabs/tab.h
+++ b/chrome/browser/views/tabs/tab.h
@@ -46,6 +46,10 @@ class Tab : public TabRenderer,
virtual bool IsCommandEnabledForTab(
TabStripModel::ContextMenuCommand command_id, const Tab* tab) const = 0;
+ // Returns true if the specified command is checked for the specified Tab.
+ virtual bool IsCommandCheckedForTab(
+ TabStripModel::ContextMenuCommand command_id, const Tab* tab) const = 0;
+
// Executes the specified command for the specified Tab.
virtual void ExecuteCommandForTab(
TabStripModel::ContextMenuCommand command_id, Tab* tab) = 0;
diff --git a/chrome/browser/views/tabs/tab_strip.cc b/chrome/browser/views/tabs/tab_strip.cc
index ec15794..80d761b 100644
--- a/chrome/browser/views/tabs/tab_strip.cc
+++ b/chrome/browser/views/tabs/tab_strip.cc
@@ -744,8 +744,7 @@ TabStrip::TabStrip(TabStripModel* model)
TabStrip::~TabStrip() {
active_animation_.reset(NULL);
- // TODO(beng): (1031854) Restore this line once XPFrame/VistaFrame are dead.
- // model_->RemoveObserver(this);
+ model_->RemoveObserver(this);
// TODO(beng): remove this if it doesn't work to fix the TabSelectedAt bug.
drag_controller_.reset(NULL);
@@ -818,6 +817,15 @@ bool TabStrip::IsCompatibleWith(TabStrip* other) const {
return model_->profile() == other->model()->profile();
}
+void TabStrip::InitFromModel() {
+ // Walk the model, calling our insertion observer method for each item within
+ // it.
+ for (int i = 0; i < model_->count(); ++i) {
+ TabInsertedAt(model_->GetTabContentsAt(i), i,
+ i == model_->selected_index());
+ }
+}
+
////////////////////////////////////////////////////////////////////////////////
// TabStrip, BaseTabStrip implementation:
@@ -1309,6 +1317,18 @@ bool TabStrip::IsCommandEnabledForTab(
return false;
}
+bool TabStrip::IsCommandCheckedForTab(
+ TabStripModel::ContextMenuCommand command_id, const Tab* tab) const {
+ // TODO(beng): move to TabStripModel, see note in IsTabPinned.
+ if (command_id == TabStripModel::CommandTogglePinned)
+ return IsTabPinned(tab);
+
+ int index = GetIndexOfTab(tab);
+ if (model_->ContainsIndex(index))
+ return model_->IsContextMenuCommandChecked(index, command_id);
+ return false;
+}
+
void TabStrip::ExecuteCommandForTab(
TabStripModel::ContextMenuCommand command_id, Tab* tab) {
int index = GetIndexOfTab(tab);
diff --git a/chrome/browser/views/tabs/tab_strip.h b/chrome/browser/views/tabs/tab_strip.h
index 6285e1d..4e2dec4 100644
--- a/chrome/browser/views/tabs/tab_strip.h
+++ b/chrome/browser/views/tabs/tab_strip.h
@@ -74,6 +74,11 @@ class TabStrip : public BaseTabStrip,
// Compatible tab strips can transfer tabs during drag and drop.
bool IsCompatibleWith(TabStrip* other) const;
+ // Populates the BaseTabStrip implementation from its model. This is primarily
+ // useful when switching between display types and there are existing tabs.
+ // Upon initial creation the TabStrip is empty.
+ void InitFromModel();
+
// BaseTabStrip implementation:
virtual int GetPreferredHeight();
virtual void SetBackgroundOffset(const gfx::Point& offset);
@@ -136,6 +141,8 @@ class TabStrip : public BaseTabStrip,
virtual void CloseTab(Tab* tab);
virtual bool IsCommandEnabledForTab(
TabStripModel::ContextMenuCommand command_id, const Tab* tab) const;
+ virtual bool IsCommandCheckedForTab(
+ TabStripModel::ContextMenuCommand command_id, const Tab* tab) const;
virtual void ExecuteCommandForTab(
TabStripModel::ContextMenuCommand command_id, Tab* tab);
virtual void StartHighlightTabsForCommand(
diff --git a/chrome/test/test_browser_window.h b/chrome/test/test_browser_window.h
index 169afdb..405f361 100644
--- a/chrome/test/test_browser_window.h
+++ b/chrome/test/test_browser_window.h
@@ -99,6 +99,7 @@ class TestBrowserWindow : public BrowserWindow {
virtual void Cut() { }
virtual void Copy() { }
virtual void Paste() { }
+ virtual void ToggleTabStripMode() { }
protected:
virtual void DestroyBrowser() {}